ऊपरी मामले में एक स्ट्रिंग को C ++ में कनवर्ट करें


268

कोई स्ट्रिंग को अपर केस में कैसे बदल सकता है। गुग्लिंग से जो उदाहरण मुझे मिले हैं, उन्हें केवल छंद से निपटना है।

जवाबों:


205

बूस्ट स्ट्रिंग एल्गोरिदम:

#include <boost/algorithm/string.hpp>
#include <string>

std::string str = "Hello World";

boost::to_upper(str);

std::string newstr = boost::to_upper_copy<std::string>("Hello World");

5
यह भी i18n का लाभ है, जहां ::toupperसबसे अधिक संभावना है ASCII।
बेन स्ट्रब

4
आपकी अंतिम पंक्ति संकलित नहीं है - आपको कुछ इस तरह बदलना होगा:std::string newstr(boost::to_upper_copy<std::string>("Hello World"));
maxschlepzig

58
यह स्वीकृत उत्तर नहीं होना चाहिए क्योंकि इसे बढ़ावा देने की आवश्यकता है, या शीर्षक को बदलना चाहिए।
एंड्रिया

44
हाँ, मैं to_upper के लिए बढ़ावा देने जा रहा हूँ ... उत्कृष्ट विचार! </ sarcasm> :)
thang

12
मैं "मैं सी ++ में एक्स कैसे करूं ?" के उत्तर के रूप में बढ़ावा देने के लिए व्यक्तिगत रूप से बीमार हूं। क्योंकि बढ़ावा बिल्कुल हल नहीं है। ऐसा लगता है कि आप या तो एक फ्रेमवर्क (या ACE या Qt या Recusion ToolKit ++ या ...) के रूप में बढ़ावा देते हैं या आप नहीं करते हैं। मैं भाषा समाधान देखना पसंद करूंगा।
jwm

486
#include <algorithm>
#include <string>

std::string str = "Hello World";
std::transform(str.begin(), str.end(),str.begin(), ::toupper);

8
दरअसल, toupper()मैक्रो के रूप में लागू किया जा सकता है। यह एक समस्या का कारण हो सकता है।
dirkgently

3
a bind (:: toupper, build <unsign char> (_ 1)) with boost.lambda पूरी तरह से ठीक काम करेगा मुझे लगता है।
जोहान्स शहाब -

11
यह दृष्टिकोण ASCII के लिए ठीक काम करता है, लेकिन मल्टी-बाइट चरित्र एन्कोडिंग के लिए, या जर्मन 'cas' जैसे विशेष आवरण नियमों के लिए विफल रहता है।
dan04

9
मैंने बूस्ट किए गए पुस्तकालयों का उपयोग करते हुए स्वीकार किए गए उत्तर को बदल दिया, क्योंकि यह (मेरे अनौपचारिक परीक्षण में) तेज था, उपयोग करना आसान था, और इस समाधान से जुड़ी समस्याएं नहीं हैं। अभी भी उदाहरणों के लिए एक अच्छा समाधान जहां बूस्ट का उपयोग नहीं किया जा सकता है।
ऑरेंजअल्मंड्सअप

2
मुझे नहीं मिल सकता है कि कंपाइलर इस कोड को बिना :: क्वालीफायर से पहले अस्वीकार क्यों करता है toupper। कोई विचार?
साशा.सोचका

89

C ++ 11 और टॉपर () का उपयोग करते हुए लघु समाधान।

for (auto & c: str) c = toupper(c);

नहीं चाहेंगे cकी हो const char(प्रकार auto)? यदि ऐसा है, तो आप इसे ( constभाग के कारण ) असाइन नहीं कर सकते हैं कि क्या लौटाया गया है toupper(c)
पोलग्राफिक

5
@ पॉलीग्राफिक: श्रेणी - कंटेनर की शुरुआत () / समाप्ति () विधियों का उपयोग इसकी सामग्री पर पुनरावृति करने के लिए। std :: basic_string में एक const और एक उत्परिवर्तित पुनरावर्तक (cbegin द्वारा लौटाया गया) और क्रमशः () (क्रमशः) देखें, std :: basic_string :: start) देखें , इसलिए (:) के लिए एक उपयुक्त (cbegin (/) का उपयोग करता है। घोषित कास्ट, ऑटो के साथ =: = कास्ट चार, शुरू () अन्यथा, ऑटो के साथ =: = चार)।
थानिसिस पापुटीसाडिसिस

5
नीचे dirkgently के anser देखें, cकरने के लिए कलाकारों की जरूरत unsigned charके लिए यह corred किया जाना है।
क्रिस लुएंगो

बूस्ट की to_upper () t ++ के मुकाबले c ++ STL फ़ंक्शन के साथ बहुत अधिक संगत है।
tartaruga_casco_mole

29
struct convert {
   void operator()(char& c) { c = toupper((unsigned char)c); }
};

// ... 
string uc_str;
for_each(uc_str.begin(), uc_str.end(), convert());

नोट: शीर्ष समाधान के साथ समस्याओं की एक जोड़ी:

21.5 अशक्त अनुक्रम उपयोगिताओं

इन हेडरों की सामग्री मानक C लाइब्रेरी हेडर <ctype.h>, <wctype.h>, <string.h>, <wchar.h>, और <stdlib.h> [... के समान होगी।

  • जिसका अर्थ है कि cctypeसदस्य अच्छी तरह से मानक एल्गोरिदम में प्रत्यक्ष खपत के लिए उपयुक्त नहीं हो सकते हैं।

  • एक ही उदाहरण के साथ एक और समस्या यह है कि यह तर्क नहीं देता है या यह सत्यापित नहीं करता है कि यह गैर-नकारात्मक है; यह उन प्रणालियों के लिए विशेष रूप से खतरनाक है जहां सादे charपर हस्ताक्षर किए गए हैं। (इसका कारण: यदि इसे एक मैक्रो के रूप में लागू किया जाता है तो यह संभवतः एक लुकअप टेबल का उपयोग करेगा और आपके तर्क उस तालिका में अनुक्रमित करेंगे। एक नकारात्मक सूचकांक आपको यूबी देगा।)


सामान्य cctype सदस्य मैक्रोज़ हैं। मुझे याद है कि उन्हें भी कार्य करना था, हालांकि मेरे पास C90 मानक की एक प्रति नहीं है और यह नहीं जानते कि यह स्पष्ट रूप से कहा गया था या नहीं।
डेविड थॉर्नले

1
उन्हें C ++ में फ़ंक्शंस होना चाहिए - भले ही सी उन्हें मैक्रोज़ होने की अनुमति दे। मैं हालांकि कास्टिंग के बारे में आपके दूसरे बिंदु से सहमत हूं। शीर्ष समाधान नकारात्मक मूल्यों को पारित कर सकता है और इसके साथ यूबी का कारण बन सकता है। कारण है कि मैं इसे वोट नहीं था अप (लेकिन मैं इसे नीचे या तो वोट नहीं किया था) :)
litb - Johannes Schaub

1
मानक उद्धरण गायब नहीं होना चाहिए: 7.4.2.2/1 (खराब लिट, जो केवल C99 TC2 ड्राफ्ट का संदर्भ दे रहा है), और C ++ 17.4.1.2/6 की महिमा c ++ 98 मानक में है।
जोहान्स स्काउब -

1
(इसे फुट-नोट नोट करें: "यह मास्किंग मैक्रो प्रदान करने की सामान्य प्रथा को अस्वीकार करता है .... ब्ला ब्लूप .. सी ++ में इसे करने का एकमात्र तरीका एक बाहरी इनलाइन फ़ंक्शन प्रदान करना है।") :)
जोहान्स शेहा -

1
... कि इस प्रवंचना से हासिल किया गया है: stackoverflow.com/questions/650461/…
जोहान्स शाउब -

27

ASCII वर्ण सेट के लिए SIMD के साथ यह समस्या वेक्टर योग्य है


स्पीडअप तुलना:

-O3 -march=nativeएक Core2Duo (मेरोम) पर x86-64 gcc 5.2 के साथ प्रारंभिक परीक्षण । 120 वर्णों का एक ही तार (मिश्रित लोअरकेस और नॉन-लोअरकेस ASCII), लूप में 40M बार (बिना क्रॉस-फाइल इनलाइन के रूप में परिवर्तित हो जाता है, इसलिए कंपाइलर लूप से बाहर किसी को भी अनुकूलित नहीं कर सकता है और न ही उखाड़ सकता है)। समान स्रोत और भाग्य बफ़र्स, इसलिए कोई भी मैलोकेट ओवरहेड या मेमोरी / कैश इफेक्ट्स नहीं है: पूरे समय एल 1 कैश में डेटा गर्म है, और हम विशुद्ध रूप से सीपीयू-बाउंड हैं।

  • boost::to_upper_copy<char*, std::string>(): 198.0 से । हां, उबंटू 15.10 पर 1.58 बूस्ट करना वास्तव में यह धीमा है। मैंने एक डीबगर में एसोम्ड और सिंगल-स्टेपम को रखा, और यह वास्तव में, वास्तव में बुरा है: प्रति वर्ण में होने वाले लोकल वैरिएबल का डायनेमिक_कास्ट है !!! (डायनेमिक_कास्ट strcmp में कई कॉल लेता है)। ऐसा LANG=Cऔर साथ होता हैLANG=en_CA.UTF-8

    मैंने std :: string के अलावा एक रेंजटी का उपयोग करके परीक्षण नहीं किया। हो सकता है कि दूसरे रूप मेंto_upper_copy बेहतर का अनुकूलन हो, लेकिन मुझे लगता है कि यह हमेशा कॉपी के लिए new/ mallocस्थान होगा , इसलिए परीक्षण करना कठिन है। हो सकता है कि मैंने जो कुछ किया था वह सामान्य उपयोग के मामले से अलग हो, और शायद सामान्य रूप से रोका गया जी ++ प्रति-वर्ण लूप से बाहर लोकेल सेटअप सामान को फहरा सकता है। मेरा लूप पढ़ना std::stringऔर लिखना char dstbuf[4096]परीक्षण के लिए समझ में आता है।

  • लूप कॉलिंग ग्लिबैकtoupper : 6.67 ( intसंभावित मल्टी-बाइट यूटीएफ -8 के लिए परिणाम की जांच नहीं करना , हालांकि यह तुर्की के लिए मायने रखता है।)

  • ASCII- केवल लूप: 8.79s (नीचे दिए गए परिणामों के लिए मेरा आधारभूत संस्करण।) जाहिरा तौर पर एक टेबल लुकअप एक से कहीं तेज है cmov, वैसे भी L1 में टेबल गर्म है।
  • ASCII- केवल ऑटो- वेक्टरकृत : 2.51 s । (सबसे खराब स्थिति और सर्वोत्तम मामले के बीच 120 वर्ण आधा रास्ता है, नीचे देखें)
  • एएससीआईआई-केवल मैन्युअल रूप से वेक्टरीकृत : 1.35s

स्थानीय स्तर पर सेट होने पर विंडोज पर धीमा होने के बारे मेंtoupper() भी यह प्रश्न देखें ।


मैं हैरान था कि बूस्ट अन्य विकल्पों की तुलना में परिमाण धीमा करने का एक क्रम है। मैंने डबल-चेक किया जो मैंने -O3सक्षम किया था , और यहां तक ​​कि एकल-चरण को भी देखा कि यह क्या कर रहा था। यह क्लैंग ++ 3.8 के साथ लगभग समान गति है। इसमें प्रति-वर्ण लूप के अंदर भारी ओवरहेड है। perf record/ reportपरिणाम (के लिए cyclesपर्फ़ घटना) है:

  32.87%  flipcase-clang-  libstdc++.so.6.0.21   [.] _ZNK10__cxxabiv121__vmi_class_type_info12__do_dyncastElNS_17__class_type_info10__sub_kindEPKS1_PKvS4_S6_RNS1_16
  21.90%  flipcase-clang-  libstdc++.so.6.0.21   [.] __dynamic_cast                                                                                                 
  16.06%  flipcase-clang-  libc-2.21.so          [.] __GI___strcmp_ssse3                                                                                            
   8.16%  flipcase-clang-  libstdc++.so.6.0.21   [.] _ZSt9use_facetISt5ctypeIcEERKT_RKSt6locale                                                                     
   7.84%  flipcase-clang-  flipcase-clang-boost  [.] _Z16strtoupper_boostPcRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE                                   
   2.20%  flipcase-clang-  libstdc++.so.6.0.21   [.] strcmp@plt                                                                                                     
   2.15%  flipcase-clang-  libstdc++.so.6.0.21   [.] __dynamic_cast@plt                                                                                             
   2.14%  flipcase-clang-  libstdc++.so.6.0.21   [.] _ZNKSt6locale2id5_M_idEv                                                                                       
   2.11%  flipcase-clang-  libstdc++.so.6.0.21   [.] _ZNKSt6locale2id5_M_idEv@plt                                                                                   
   2.08%  flipcase-clang-  libstdc++.so.6.0.21   [.] _ZNKSt5ctypeIcE10do_toupperEc                                                                                  
   2.03%  flipcase-clang-  flipcase-clang-boost  [.] _ZSt9use_facetISt5ctypeIcEERKT_RKSt6locale@plt                                                                 
   0.08% ...

Autovectorization

Gcc और क्लैंग केवल ऑटो-वेक्टराइज़ लूप होंगे, जब पुनरावृति गणना को लूप के आगे जाना जाता है। (यानी सर्च-लूप जैसे सादे-सी का कार्यान्वयन strlenऑटोव्रॉइज़ नहीं होगा।)

इस प्रकार, कैश में फिट होने के लिए छोटे स्ट्रिंग्स के लिए, हम स्ट्रिंग्स के लिए एक महत्वपूर्ण स्पीडअप प्राप्त करते हैं ~ 128 चार्ट strlenपहले करने से लंबे । यह स्पष्ट लंबाई के तार (जैसे C ++ std::string) के लिए आवश्यक नहीं होगा ।

// char, not int, is essential: otherwise gcc unpacks to vectors of int!  Huge slowdown.
char ascii_toupper_char(char c) {
    return ('a' <= c && c <= 'z') ? c^0x20 : c;    // ^ autovectorizes to PXOR: runs on more ports than paddb
}

// gcc can only auto-vectorize loops when the number of iterations is known before the first iteration.  strlen gives us that
size_t strtoupper_autovec(char *dst, const char *src) {
    size_t len = strlen(src);
    for (size_t i=0 ; i<len ; ++i) {
        dst[i] = ascii_toupper_char(src[i]);  // gcc does the vector range check with psubusb / pcmpeqb instead of pcmpgtb
    }
    return len;
}

किसी भी सभ्य लिबास में एक कुशल होगा strlen एक बार में एक बाइट को लूप करने की तुलना में बहुत तेज होता है, इसलिए अलग-अलग वेक्टरकृत स्ट्रलेन और टॉपर लूप तेजी से होते हैं।

बेसलाइन: एक लूप जो मक्खी पर एक समाप्ति 0 के लिए जाँच करता है।

402 पुनरावृत्तियों के लिए टाइम्स, एक Core2 (मेरोम) 2.4GHz पर। gcc 5.2 -O3 -march=native। (Ubuntu 15.10)। dst != src(इसलिए हम एक प्रति बनाते हैं), लेकिन वे ओवरलैप नहीं करते हैं (और पास नहीं हैं)। दोनों गठबंधन कर रहे हैं।

  • 15 चार स्ट्रिंग: आधार रेखा: 1.08s। ऑटोवेक: 1.34s
  • 16 चार स्ट्रिंग: आधार रेखा: 1.16। ऑटोवेक: 1.52 एस
  • 127 चार स्ट्रिंग: आधार रेखा: 8.91s। autovec: 2.98s // गैर-वेक्टर सफाई में प्रक्रिया के लिए 15 वर्ण हैं
  • 128 चार स्ट्रिंग: आधार रेखा: 9.00s। ऑटोवेक: 2.06 s
  • 129 चार स्ट्रिंग: आधार रेखा: 9.04। ऑटोवेक: 2.07 एस // गैर-वेक्टर सफाई में प्रक्रिया के लिए 1 चार्ट है

क्लैंग के साथ कुछ परिणाम थोड़े अलग हैं।

फ़ंक्शन को कॉल करने वाला माइक्रोबेनमार्क लूप एक अलग फ़ाइल में है। अन्यथा यह सुर्खियों में है औरstrlen() लूप से बाहर हो जाता है, और यह नाटकीय रूप से तेज, एस्प चलाता है। 16 चार तार के लिए (0.187s)।

इसका प्रमुख लाभ यह है कि gcc इसे किसी भी आर्किटेक्चर के लिए ऑटो-वेक्टर कर सकता है, लेकिन मुख्य नुकसान यह है कि यह छोटे तारों के आमतौर पर सामान्य मामले के लिए धीमा है।


तो बड़े स्पीडअप हैं, लेकिन कंपाइलर ऑटो-वैरिफिकेशन महान कोड, एस्प नहीं बनाता है। अंतिम-से -15 वर्णों की सफाई के लिए।

SSE आंतरिक विज्ञान के साथ मैनुअल वेक्टरकरण:

मेरे केस-फ्लिप फंक्शन के आधार पर जो हर अल्फ़ाबेटिक चरित्र के मामले को प्रभावित करता है। यह "अहस्ताक्षरित तुलना चाल" का लाभ उठाता है, जहां आप low < a && a <= highएक ही अहस्ताक्षरित तुलना रेंज शिफ्टिंग के साथ कर सकते हैं , ताकि किसी मूल्य से कम मूल्य वाले मान से lowअधिक हो high। (यह काम करता है अगर lowऔरhigh बहुत दूर नहीं है।)

SSE में केवल एक हस्ताक्षरित तुलना-अधिक है, लेकिन हम अभी भी हस्ताक्षरित सीमा के नीचे शिफ्टिंग द्वारा "अहस्ताक्षरित तुलना" चाल का उपयोग कर सकते हैं: 'a' + 128 को घटाएँ, इसलिए वर्णमाला के वर्ण -128 से -128 +26 (-128 + 'z' - 'a')

ध्यान दें कि 128 जोड़ना और 128 घटाना 8bit पूर्णांक के लिए एक ही बात है। ले जाने के लिए कहीं नहीं है, इसलिए यह सिर्फ एक्सर (कैरीलेस ऐड) है, उच्च बिट को फ़्लिप करता है।

#include <immintrin.h>

__m128i upcase_si128(__m128i src) {
    // The above 2 paragraphs were comments here
    __m128i rangeshift = _mm_sub_epi8(src, _mm_set1_epi8('a'+128));
    __m128i nomodify   = _mm_cmpgt_epi8(rangeshift, _mm_set1_epi8(-128 + 25));  // 0:lower case   -1:anything else (upper case or non-alphabetic).  25 = 'z' - 'a'

    __m128i flip  = _mm_andnot_si128(nomodify, _mm_set1_epi8(0x20));            // 0x20:lcase    0:non-lcase

    // just mask the XOR-mask so elements are XORed with 0 instead of 0x20
    return          _mm_xor_si128(src, flip);
    // it's easier to xor with 0x20 or 0 than to AND with ~0x20 or 0xFF
}

एक वेक्टर के लिए काम करने वाले इस फ़ंक्शन को देखते हुए, हम इसे पूरे स्ट्रिंग को संसाधित करने के लिए लूप में कह सकते हैं। चूंकि हम पहले से ही SSE2 को लक्षित कर रहे हैं, हम एक ही समय में एक वेक्टर-एंड-ऑफ-स्ट्रिंग चेक कर सकते हैं।

हम 16B के वैक्टर करने के बाद बचे हुए अप -15-बाइट्स के "क्लीनअप" के लिए बहुत बेहतर कर सकते हैं: अपर-केसिंग एक प्रकार का कोमल है, इसलिए कुछ इनपुट बाइट्स को पुन: संसाधित करना ठीक है। हम स्रोत के अंतिम 16B का एक अनलिज्ड लोड करते हैं, और इसे लूप से अंतिम 16B स्टोर को ओवरलैप करने वाले डेस्ट बफर में स्टोर करते हैं।

केवल यह समय काम नहीं करता है जब पूरी स्ट्रिंग 16B से कम है: तब भी dst=src, जब गैर-परमाणु परमाणु-संशोधित-लेखन नहीं है समान चीज जो कुछ बाइट्स को नहीं छूता है, और मल्टीथ्रेडेड कोड को तोड़ सकता है।

हमारे पास इसके लिए एक स्केलर लूप है, और srcसंरेखित करने के लिए भी । चूँकि हमें नहीं पता कि समाप्ति ० कहाँ होगी, एक अनराल्ड लोड srcअगले पृष्ठ और सेगफॉल्ट में पार हो सकता है। अगर हमें 16B के किसी भी बंक को किसी बाइट्स की आवश्यकता है, तो पूरे संरेखित 16B चंक को लोड करना हमेशा सुरक्षित होता है।

पूर्ण स्रोत: एक GitHub सार में

// FIXME: doesn't always copy the terminating 0.
// microbenchmarks are for this version of the code (with _mm_store in the loop, instead of storeu, for Merom).
size_t strtoupper_sse2(char *dst, const char *src_begin) {
    const char *src = src_begin;
    // scalar until the src pointer is aligned
    while ( (0xf & (uintptr_t)src) && *src ) {
        *(dst++) = ascii_toupper(*(src++));
    }

    if (!*src)
        return src - src_begin;

    // current position (p) is now 16B-aligned, and we're not at the end
    int zero_positions;
    do {
        __m128i sv = _mm_load_si128( (const __m128i*)src );
        // TODO: SSE4.2 PCMPISTRI or PCMPISTRM version to combine the lower-case and '\0' detection?

        __m128i nullcheck = _mm_cmpeq_epi8(_mm_setzero_si128(), sv);
        zero_positions = _mm_movemask_epi8(nullcheck);
        // TODO: unroll so the null-byte check takes less overhead
        if (zero_positions)
            break;

        __m128i upcased = upcase_si128(sv);   // doing this before the loop break lets gcc realize that the constants are still in registers for the unaligned cleanup version.  But it leads to more wasted insns in the early-out case

        _mm_storeu_si128((__m128i*)dst, upcased);
        //_mm_store_si128((__m128i*)dst, upcased);  // for testing on CPUs where storeu is slow
        src += 16;
        dst += 16;
    } while(1);

    // handle the last few bytes.  Options: scalar loop, masked store, or unaligned 16B.
    // rewriting some bytes beyond the end of the string would be easy,
    // but doing a non-atomic read-modify-write outside of the string is not safe.
    // Upcasing is idempotent, so unaligned potentially-overlapping is a good option.

    unsigned int cleanup_bytes = ffs(zero_positions) - 1;  // excluding the trailing null
    const char* last_byte = src + cleanup_bytes;  // points at the terminating '\0'

    // FIXME: copy the terminating 0 when we end at an aligned vector boundary
    // optionally special-case cleanup_bytes == 15: final aligned vector can be used.
    if (cleanup_bytes > 0) {
        if (last_byte - src_begin >= 16) {
            // if src==dest, this load overlaps with the last store:  store-forwarding stall.  Hopefully OOO execution hides it
            __m128i sv = _mm_loadu_si128( (const __m128i*)(last_byte-15) ); // includes the \0
            _mm_storeu_si128((__m128i*)(dst + cleanup_bytes - 15), upcase_si128(sv));
        } else {
            // whole string less than 16B
            // if this is common, try 64b or even 32b cleanup with movq / movd and upcase_si128
#if 1
            for (unsigned int i = 0 ; i <= cleanup_bytes ; ++i) {
                dst[i] = ascii_toupper(src[i]);
            }
#else
            // gcc stupidly auto-vectorizes this, resulting in huge code bloat, but no measurable slowdown because it never runs
            for (int i = cleanup_bytes - 1 ;  i >= 0 ; --i) {
                dst[i] = ascii_toupper(src[i]);
            }
#endif
        }
    }

    return last_byte - src_begin;
}

402 पुनरावृत्तियों के लिए टाइम्स, एक Core2 (मेरोम) 2.4GHz पर। gcc 5.2 -O3 -march=native। (Ubuntu 15.10)। dst != src(इसलिए हम एक प्रति बनाते हैं), लेकिन वे ओवरलैप नहीं करते हैं (और पास नहीं हैं)। दोनों गठबंधन कर रहे हैं।

  • 15 चार स्ट्रिंग: आधार रेखा: 1.08s। ऑटोवेक: 1.34s। मैनुअल: 1.29 s
  • 16 चार स्ट्रिंग: आधार रेखा: 1.16। ऑटोवेक: 1.52 एस। मैनुअल: 0.335 s
  • 31 चार स्ट्रिंग: मैनुअल: 0.479 एस
  • 127 चार स्ट्रिंग: आधार रेखा: 8.91s। ऑटोवेक: 2.98s। मैनुअल: 0.925 s
  • 128 चार स्ट्रिंग: आधार रेखा: 9.00s। ऑटोवेक: 2.06 s। मैनुअल: 0.931 एस
  • 129 चार स्ट्रिंग: आधार रेखा: 9.04। ऑटोवेक: 2.07 एस। मैनुअल: 1.02s

(वास्तव _mm_storeमें लूप में समय के साथ , नहीं _mm_storeu, क्योंकि स्टोरू मेरोम पर धीमी है, यहां तक ​​कि जब पता संरेखित किया जाता है। यह नेहल्म और बाद में ठीक है। मैंने भी कोड को छोड़ दिया है-अब के लिए, कॉपी करने में विफलता को ठीक करने के बजाय। कुछ मामलों में समाप्ति 0, क्योंकि मैं सब कुछ फिर से नहीं करना चाहता।)

तो 16B से छोटे तार के लिए, यह ऑटो-वेक्टर से नाटकीय रूप से तेज़ है। लंबाई एक-से-एक-वेक्टर-चौड़ाई एक समस्या पेश नहीं करती है। स्टोर-फ़ॉरवर्डिंग स्टॉल के कारण, इन-प्लेस संचालन करते समय उन्हें समस्या हो सकती है। (लेकिन ध्यान दें कि मूल इनपुट के बजाय हमारे स्वयं के आउटपुट को संसाधित करने के लिए अभी भी ठीक है, क्योंकि टौपर बेकार है)।

अलग-अलग उपयोग-मामलों के लिए इसे ट्यूनिंग के लिए बहुत गुंजाइश है, जो आस-पास के कोड को लक्षित करता है, और लक्ष्य माइक्रोआर्किटेक्चर पर निर्भर करता है। कंपाइलर को क्लीनअप भाग के लिए अच्छा कोड प्राप्त करना मुश्किल है। का उपयोग करना ffs(3)(जो x86 पर bsf या tzcnt को संकलित करता है) अच्छा प्रतीत होता है, लेकिन जाहिर है कि बिट को फिर से सोचने की जरूरत है क्योंकि मैंने इस उत्तर को लिखने के बाद एक बग देखा (FIXME टिप्पणियों को देखें)।

यहां तक ​​कि छोटे तारों के लिए वेक्टर स्पीडअप movqया movdलोड / स्टोर के साथ प्राप्त किया जा सकता है । अपने उपयोग-मामले के लिए आवश्यकतानुसार अनुकूलित करें।


UTF-8:

हम पता लगा सकते हैं कि जब हमारे वेक्टर में उच्च बिट सेट के साथ कोई बाइट्स होता है, और उस स्थिति में उस वेक्टर के लिए एक स्केलर utf-8-जागरूक लूप में वापस आते हैं। dstबिंदु से एक अलग राशि से अग्रिम कर सकते हैं srcसूचक, लेकिन एक बार हम वापस एक गठबंधन करने के लिए मिलता srcसूचक, हम अभी भी सिर्फ असंरेखित वेक्टर दुकानों के लिए क्या करेंगे dst

पाठ के लिए जो UTF-8 है, लेकिन ज्यादातर में UTF-8 का ASCII सबसेट शामिल है, यह अच्छा हो सकता है: सभी मामलों में सही व्यवहार के साथ सामान्य मामले में उच्च प्रदर्शन। जब बहुत अधिक गैर-एएससीआईआई होता है, तो यह संभवतः हर समय स्केलर UTF-8 जागरूक लूप में रहने से भी बदतर होगा।

अन्य भाषाओं की कीमत पर अंग्रेजी को तेज बनाना एक नकारात्मक प्रमाण नहीं है, अगर नकारात्मक पक्ष महत्वपूर्ण है।


लोकेल अवगत:

तुर्की स्थान में ( tr_TR), से सही परिणाम toupper('i')है 'İ'(U0130), नहीं 'I'(सादे ASCII)। विंडोज पर स्लो होने के सवाल पर मार्टिन बोनर की टिप्पणी देखें tolower()

हम मल्टी-बाइट UTF8 इनपुट वर्णों की तरह, एक अपवाद-सूची और वहां स्केलर पर कमबैक के लिए भी जांच कर सकते हैं।

इस जटिलता के साथ, SSE4.2 PCMPISTRMया कुछ एक बार में हमारी बहुत सारी जाँच करने में सक्षम हो सकता है।


20

क्या आपके पास तार में ASCII या अंतर्राष्ट्रीय वर्ण हैं?

यदि यह बाद का मामला है, तो "अपरकेसिंग" इतना आसान नहीं है, और यह प्रयुक्त वर्णमाला पर निर्भर करता है। द्विसदनीय और द्विसदनीय वर्णमालाएं हैं। केवल द्विसदनीय वर्णमाला में ऊपरी और निचले मामले के लिए अलग-अलग वर्ण होते हैं। इसके अलावा, मिश्रित अक्षर हैं, जैसे लैटिन कैपिटल लेटर 'DZ' (\ u01F1 'DZ') जो तथाकथित का उपयोग करते हैं शीर्षक शीर्षक का । इसका मतलब है कि केवल पहला चरित्र (डी) बदल जाता है।

मेरा सुझाव है कि आप में देखो आईसीयू में देखें , और सिंपल और फुल केस मैपिंग में अंतर करें। यह मदद कर सकता है:

http://userguide.icu-project.org/transforms/casemappings


7
या जर्मन एसज़ेट (स्प?), वह चीज़ जो ग्रीक अक्षर बीटा की तरह दिखती है, और जिसका अर्थ है "ss"। कोई भी जर्मन वर्ण नहीं है जिसका अर्थ है "एसएस", जो कि अपरकेस समान है। "सड़क" के लिए जर्मन शब्द, जब अपरकेस होता है, तो एक वर्ण लंबा हो जाता है।
डेविड थॉर्नले

6
एक अन्य विशेष मामला ग्रीक अक्षर सिग्मा (,) है, जिसमें दो लोअरकेस संस्करण हैं, जो इस बात पर निर्भर करता है कि यह किसी शब्द (a) के अंत में है या नहीं (σ)। और फिर भाषा के विशिष्ट नियम हैं, जैसे कि तुर्की में मामले की मैपिंग I andı और specifici है।
dan04

1
"अपरकेसिंग" को केस फोल्डिंग कहा जाता है।
कोलंबो

20
string StringToUpper(string strToConvert)
{
   for (std::string::iterator p = strToConvert.begin(); strToConvert.end() != p; ++p)
       *p = toupper(*p);

   return p;
}

या,

string StringToUpper(string strToConvert)
{
    std::transform(strToConvert.begin(), strToConvert.end(), strToConvert.begin(), ::toupper);

    return strToConvert;
}

4
यदि आपके पास दूसरे समाधान को बढ़ावा देने के लिए पहुंच नहीं है, तो शायद सबसे अच्छा आप प्राप्त कर सकते हैं। **पहले समाधान पर मापदंडों के बाद सितारे क्या करते हैं?
सैम ब्रिनक

1
मुझे पूरा यकीन **है कि कोड सिंटैक्स में बोल्ड फ़ॉन्ट का उपयोग करने की कोशिश से बचा हुआ एक टाइपो है।
मास्टरएचडी

1
जब toupperनकारात्मक संख्याओं के साथ कॉल किया जाता है तो यह कोड अपरिभाषित व्यवहार को आमंत्रित करता है।
रोलैंड इलिग

17

निम्नलिखित मेरे लिए काम करता है।

#include <algorithm>
void  toUpperCase(std::string& str)
{
    std::transform(str.begin(), str.end(), str.begin(), ::toupper);
}

int main()
{
   std::string str = "hello";
   toUpperCase(&str);
}

ध्यान दें कि std :: ट्रांस्फ़ॉर्मेशन <एल्गोरिथम>
edj

हाँ। इसमें # शामिल होना आवश्यक है, #include <एल्गोरिथम>
पाबित्रा डैश

1
जब toupperनकारात्मक संख्याओं के साथ कॉल किया जाता है तो यह कोड अपरिभाषित व्यवहार को आमंत्रित करता है।
रोलैंड इलिग

user648545 द्वारा दिए गए जवाब की नकल - -1
पिओर Dobrogost

@PiotrDobrogost मुझे user648545 द्वारा दिए गए उत्तर के बारे में कोई जानकारी नहीं है। मैंने कॉपी नहीं किया है। जब मैं दो तरीकों की तुलना विधि हस्ताक्षर को पूरी तरह से अलग करता हूं, हालांकि दोनों फ़ंक्शन लाइब्रेरी फ़ंक्शन ट्रांसफ़ॉर्म का उपयोग करते हैं।
पाबितरा डैश

13

एक मेमने का उपयोग करें।

std::string s("change my case");

auto to_upper = [] (char_t ch) { return std::use_facet<std::ctype<char_t>>(std::locale()).toupper(ch); };

std::transform(s.begin(), s.end(), s.begin(), to_upper);

2
बायरन, अन्य टिप्पणियों के बारे में चिंता न करें। आपके द्वारा किए गए नए (आधुनिक) समाधान के साथ पुराने प्रश्नों का उत्तर देना काफी ठीक है।
Kyberias

13

यदि आप केवल ASCII वर्णों का उपयोग करते हैं तो तेज़ :

for(i=0;str[i]!=0;i++)
  if(str[i]<='z' && str[i]>='a')
    str[i]-=32;

कृपया ध्यान दें कि यह कोड तेजी से चलता है लेकिन केवल ASCII पर काम करता है और "सार" समाधान नहीं है।

यदि आपको UNICODE समाधान या अधिक पारंपरिक और सार समाधान चाहिए, तो अन्य उत्तरों के लिए जाएं और C ++ स्ट्रिंग्स के तरीकों के साथ काम करें।


1
प्रश्न के रूप में टैग किया गया है C++, लेकिन आपने Cयहां एक उत्तर लिखा है। (मैं
नीच में से

6
मैंने एक C उत्तर लिखा और C ++ उत्तर यहाँ बीक्युसे C ++ को C स्रोतों के साथ पूरी तरह से संगत लिखा गया है, इसलिए कोई भी C समाधान C ++ सही समाधान भी है
Luca C.

लेकिन यह एक उत्तर देने के लिए इतना बेहतर है जो सी ++ तरीके का सम्मान करता है।
दिमित्रि युरचेंको

मानक c ++ तरीका std :: toupper के साथ बदलना होगा। यह कम कोड है और निश्चित रूप से पोर्टेबल है। यह कोड "तथ्य" पर भरोसा करता है कि सिस्टम एससीआई का उपयोग चरित्र एन्कोडिंग तंत्र के रूप में करेगा। सुनिश्चित नहीं है कि सभी सिस्टम इस एन्कोडिंग पर आधारित हैं और इसलिए यह सुनिश्चित नहीं है कि यह पोर्टेबल है।
एलेक्सिमो

1
आपने जिन वर्णों में संलग्न हैं, उनके बजाय ASCII कोड का उपयोग करने का निर्णय क्यों लिया '?
15

11

जब तक आप एएससीआईआई-ओनली के साथ ठीक हैं और आप आरडब्ल्यू मेमोरी को एक वैध सूचक प्रदान कर सकते हैं, सी में एक सरल और बहुत प्रभावी एक-लाइनर है:

void strtoupper(char* str)
{ 
    while (*str) *(str++) = toupper((unsigned char)*str);
}

यह विशेष रूप से सरल तार के लिए अच्छा है जैसे कि ASCII पहचानकर्ता जिसे आप एक ही चरित्र-मामले में सामान्य करना चाहते हैं। तब आप std: string आवृत्ति का निर्माण करने के लिए बफर का उपयोग कर सकते हैं।


एक नोट है कि यह उत्तर एक
एसडी के

यह एक स्पष्ट अंतर्निहित सुरक्षा दोष है। मैं ऐसा नहीं करूंगा।
बायरन

9
//works for ASCII -- no clear advantage over what is already posted...

std::string toupper(const std::string & s)
{
    std::string ret(s.size(), char());
    for(unsigned int i = 0; i < s.size(); ++i)
        ret[i] = (s[i] <= 'z' && s[i] >= 'a') ? s[i]-('a'-'A') : s[i];
    return ret;
}

s.size () प्रकार std का है :: size_t जो, AFAIK कार्यान्वयन के आधार पर बहुत अच्छी तरह से अहस्ताक्षरित int हो सकता है
odinthenerd

मुझे नहीं लगता कि कोई भी आधुनिक कार्यान्वयन है जिसमें std :: string :: size के परिणाम पर हस्ताक्षर किए गए हैं। यह देखते हुए कि, शब्दार्थ और व्यावहारिक रूप से, नकारात्मक आकार जैसी कोई चीज नहीं है, मैं size_t कम से कम 32-बिट अहस्ताक्षरित पूर्णांक के साथ जाने वाला हूं।
user1329482

लिखने का कोई कारण नहीं है for (size_t i = 0 ...। इसे पढ़ने में इतनी मेहनत करने का कोई अच्छा कारण भी नहीं है। यह स्ट्रिंग को पहले कॉपी करता है और फिर उस पर लूप करता है। @ 'a'चरित्र कांस्टेंट का फायदा नहीं उठाने के अलावा ल्यूक का जवाब कुछ मायनों में बेहतर है ।
पीटर कॉर्डेस

9
#include <string>
#include <locale>

std::string str = "Hello World!";
auto & f = std::use_facet<std::ctype<char>>(std::locale());
f.toupper(str.data(), str.data() + str.size());

यह उन सभी उत्तरों से बेहतर प्रदर्शन करेगा जो वैश्विक टॉपर फ़ंक्शन का उपयोग करते हैं, और संभवतः यह है कि :: to_upper क्या बढ़ावा दे रहा है।

ऐसा इसलिए है क्योंकि :: टॉपर को लोकेल को देखना पड़ता है - क्योंकि यह हर आह्वान के लिए - एक अलग थ्रेड द्वारा बदल दिया गया हो सकता है, जबकि यहां केवल लोकेल () में कॉल करने पर यह जुर्माना लगता है। और लोकेल को देखने में आमतौर पर ताला लगाना शामिल होता है।

आपके द्वारा ऑटो को बदलने के बाद यह C ++ 98 के साथ भी काम करता है, नए नॉन-कास्ट str.data () का उपयोग करें, और इस तरह टेम्पलेट समापन (">>" से ">">) को तोड़ने के लिए एक स्थान जोड़ें:

std::use_facet<std::ctype<char> > & f = 
    std::use_facet<std::ctype<char> >(std::locale());
f.toupper(const_cast<char *>(str.data()), str.data() + str.size());

7
typedef std::string::value_type char_t;

char_t up_char( char_t ch )
{
    return std::use_facet< std::ctype< char_t > >( std::locale() ).toupper( ch );
}

std::string toupper( const std::string &src )
{
    std::string result;
    std::transform( src.begin(), src.end(), std::back_inserter( result ), up_char );
    return result;
}

const std::string src  = "test test TEST";

std::cout << toupper( src );

के रूप में आप पहले से ही लंबाई पता है कि एक back_inserter की सिफारिश नहीं करेगा; std का उपयोग करें: स्ट्रिंग परिणाम (src.size ()); std :: transform (src.begin (), src.end (), result.begin (), up_char);
विक्टर सेहर

मुझे पूरा यकीन है कि आप यह जानते हैं।
विक्टर सेहर

@Viktor Sehr, @bayda: मुझे पता है कि यह 2 साल पुराना है, लेकिन दोनों दुनिया का सर्वश्रेष्ठ क्यों नहीं मिला। का प्रयोग करें reserveऔर back_inserter(बनाने इसलिए स्ट्रिंग केवल एक बार की नकल की है)। inline std::string to_lower(const std::string &s) { std::string result; result.reserve(s.size()); std::transform(s.begin(), s.end(), std::back_inserter( result ), static_cast<int(*)(int)>(std::tolower)); return result; }
इवान टेरान


2

toupper()फ़ंक्शन का प्रयास करें ( #include <ctype.h>)। यह वर्णों को तर्क के रूप में स्वीकार करता है, तार पात्रों से बने होते हैं, इसलिए आपको प्रत्येक व्यक्तिगत चरित्र पर पुनरावृति करनी होगी, जब एक साथ रखा जाता है जिसमें तार शामिल होते हैं


यह सुझाव toupperनकारात्मक संख्याओं के साथ अपरिभाषित व्यवहार को आमंत्रित करता है। आपको आवश्यक कलाकारों का उल्लेख करना चाहिए unsigned char
रोलैंड इलिग

2

यहाँ C ++ 11 के साथ नवीनतम कोड है

std::string cmd = "Hello World";
for_each(cmd.begin(), cmd.end(), [](char& in){ in = ::toupper(in); });

जब toupperनकारात्मक संख्याओं के साथ कॉल किया जाता है तो यह कोड अपरिभाषित व्यवहार को आमंत्रित करता है।
रोलैंड इलिग

1

Boost.Text का उपयोग करना, जो यूनिकोड पाठ के लिए काम करेगा

boost::text::text t = "Hello World";
boost::text::text uppered;
boost::text::to_title(t, std::inserter(uppered, uppered.end()));
std::string newstr = uppered.extract();

1

जवाब के @dirkgently बहुत प्रेरणादायक है, लेकिन मुझे लगता है कि जोर देना चिंता के कारण के रूप में नीचे दिखाया गया है चाहते हैं,

से अन्य सभी कार्यों की तरह, एसटीडी का व्यवहार :: टॉपर अपरिभाषित है यदि तर्क का मान न तो अहस्ताक्षरित चार के रूप में प्रतिनिधित्व करता है और न ही ईओएफ के बराबर है। सादे कार्यों (या हस्ताक्षरित वर्ण) के साथ इन कार्यों को सुरक्षित रूप से उपयोग करने के लिए, तर्क को पहले अहस्ताक्षरित चार संदर्भ में परिवर्तित किया जाना चाहिए : std ::oupper

का सही उपयोग std::toupperहोना चाहिए:

#include <algorithm>
#include <cctype>
#include <iostream>
#include <iterator>
#include <string>

void ToUpper(std::string& input)
{
    std::for_each(std::begin(input), std::end(input), [](char& c) {
        c = static_cast<char>(std::toupper(static_cast<unsigned char>(c)));
    });
}

int main()
{
    std::string s{ "Hello world!" };
    std::cout << s << std::endl;
    ::ToUpper(s);
    std::cout << s << std::endl;

    return 0;
}

आउटपुट:

Hello world!
HELLO WORLD!

0

सुनिश्चित नहीं है कि कोई अंतर्निहित फ़ंक्शन है। इसे इस्तेमाल करे:

या तो ctype.h या cctype लाइब्रेरीज़, साथ ही stdlib.h को प्रीप्रोसेसर निर्देशों के हिस्से के रूप में शामिल करें।

string StringToUpper(string strToConvert)
{//change each element of the string to upper case
   for(unsigned int i=0;i<strToConvert.length();i++)
   {
      strToConvert[i] = toupper(strToConvert[i]);
   }
   return strToConvert;//return the converted string
}

string StringToLower(string strToConvert)
{//change each element of the string to lower case
   for(unsigned int i=0;i<strToConvert.length();i++)
   {
      strToConvert[i] = tolower(strToConvert[i]);
   }
   return strToConvert;//return the converted string
}

.length () प्रकार का नहीं है 'अहस्ताक्षरित int'
malat

जब toupperनकारात्मक संख्याओं के साथ कॉल किया जाता है तो यह कोड अपरिभाषित व्यवहार को आमंत्रित करता है।
रोलैंड इलिग

0

मेरा समाधान (अल्फा के लिए 6 बिट साफ़ करना):

#include <ctype.h>

inline void toupper(char* str)
{
    while (str[i]) {
        if (islower(str[i]))
            str[i] &= ~32; // Clear bit 6 as it is what differs (32) between Upper and Lowercases
        i++;
    }
}

जब toupperनकारात्मक संख्याओं के साथ कॉल किया जाता है तो यह कोड अपरिभाषित व्यवहार को आमंत्रित करता है।
रोलैंड इलिग

नहीं ... कृपया जांच करें कि आप डाउनवॉट करने से पहले सही हैं। Islower केवल गैर नकारात्मक मूल्यों पर काम करेगा ...
एंटोनिन GAVREL

-1

इस पृष्ठ पर इन सभी समाधानों की तुलना में वे कठिन हैं जो उन्हें होना चाहिए।

यह करो

RegName = "SomE StRing That you wAnt ConvErTed";
NameLength = RegName.Size();
for (int forLoop = 0; forLoop < NameLength; ++forLoop)
{
     RegName[forLoop] = tolower(RegName[forLoop]);
}

RegNameअपने है string। अपने स्ट्रिंग आकार string.size()को अपने वास्तविक परीक्षक के रूप में उपयोग न करें , बहुत गड़बड़ है और मुद्दों का कारण बन सकता है। फिर। सबसे बुनियादीfor लूप।

याद रखें कि स्ट्रिंग का आकार सीमांकक लौटाता है इसलिए अपने लूप टेस्ट में <और नहीं <= का उपयोग करें।

आउटपुट होगा: कुछ स्ट्रिंग जो आप कनवर्ट करना चाहते हैं


4
मैं यह कैसे बढ़ावा :: टौपर समाधान की तुलना में सरल है देख नहीं है। क्या आप विस्तार से समझा सकते हैं?
tr9sh

2
पहले से ही बहुत सारे सरल tolowerलूप हैं, और उनमें से ज्यादातर मानक लूप चर नामों का उपयोग करते हैं i, जैसे कि अजीब नहीं forLoop
पीटर कॉर्डेस

-1

किसी भी पुस्तकालय का उपयोग किए बिना:

std::string YourClass::Uppercase(const std::string & Text)
{
    std::string UppperCaseString;
    UppperCaseString.reserve(Text.size());
    for (std::string::const_iterator it=Text.begin(); it<Text.end(); ++it)
    {
        UppperCaseString.push_back(((0x60 < *it) && (*it < 0x7B)) ? (*it - static_cast<char>(0x20)) : *it);
    }
    return UppperCaseString;
}

उपरोक्त कोड केवल ASCII- संगत एन्कोडिंग के लिए काम करता है। न तो आपके प्रश्न का उत्तर इस प्रतिबंध का उल्लेख करता है। उनमें से एक चाहिए।
रोलैंड इलिग

-1

यदि आप केवल 8 बिट पात्रों से संबंधित हैं (जो कि मिलान बाबुचकोव को छोड़कर अन्य सभी उत्तरों के साथ-साथ) आप मेटाप्रोग्रामिंग का उपयोग करके संकलन समय पर एक लुक-अप तालिका बनाकर सबसे तेज़ गति प्राप्त कर सकते हैं। Ideone.com पर यह लाइब्रेरी फंक्शन की तुलना में 7 गुना अधिक तेज है और हाथ से लिखे संस्करण ( http://ideone.com/sb1Rit ) की तुलना में तेजी से 3x है । यह भी धीमा नहीं के साथ लक्षण के माध्यम से अनुकूलन योग्य है।

template<int ...Is>
struct IntVector{
using Type = IntVector<Is...>;
};

template<typename T_Vector, int I_New>
struct PushFront;
template<int ...Is, int I_New>
struct PushFront<IntVector<Is...>,I_New> : IntVector<I_New,Is...>{};

template<int I_Size, typename T_Vector = IntVector<>>
struct Iota : Iota< I_Size-1, typename PushFront<T_Vector,I_Size-1>::Type> {};
template<typename T_Vector>
struct Iota<0,T_Vector> : T_Vector{};

template<char C_In>
struct ToUpperTraits {
    enum { value = (C_In >= 'a' && C_In <='z') ? C_In - ('a'-'A'):C_In };
};

template<typename T>
struct TableToUpper;
template<int ...Is>
struct TableToUpper<IntVector<Is...>>{
    static char at(const char in){
        static const char table[] = {ToUpperTraits<Is>::value...};
        return table[in];
    }
};

int tableToUpper(const char c){
    using Table = TableToUpper<typename Iota<256>::Type>;
    return Table::at(c);
}

उपयोग के मामले के साथ:

std::transform(in.begin(),in.end(),out.begin(),tableToUpper);

गहराई से (कई पृष्ठ) यह कैसे काम करता है की डिक्रीप्शन ने मुझे बेशर्मी से अपने ब्लॉग को प्लग करने की अनुमति दी: http://metaporky.blogspot.de/2014/07/part-4-generating-look-up-tables-at.html


-1
template<size_t size>
char* toupper(char (&dst)[size], const char* src) {
    // generate mapping table once
    static char maptable[256];
    static bool mapped;
    if (!mapped) {
        for (char c = 0; c < 256; c++) {
            if (c >= 'a' && c <= 'z')
                maptable[c] = c & 0xdf;
            else
                maptable[c] = c;
        }
        mapped = true;
    }

    // use mapping table to quickly transform text
    for (int i = 0; *src && i < size; i++) {
        dst[i] = maptable[*(src++)];
    }
    return dst;
}

-1

यह c ++ फ़ंक्शन हमेशा ऊपरी केस स्ट्रिंग लौटाता है ...

#include <locale> 
#include <string>
using namespace std; 
string toUpper (string str){
    locale loc; 
    string n; 
    for (string::size_type i=0; i<str.length(); ++i)
        n += toupper(str[i], loc);
    return n;
}

-3

मैं इस समाधान का उपयोग करता हूं। मुझे पता है कि आप उस डेटा क्षेत्र को संशोधित करने वाले नहीं हैं .... लेकिन मुझे लगता है कि यह ज्यादातर बफर कीड़े और अशक्त चरित्र के लिए है .... ऊपरी आवरण वाली चीजें समान नहीं हैं।

void to_upper(const std::string str) {
    std::string::iterator it;
    int i;
    for ( i=0;i<str.size();++i ) {
        ((char *)(void *)str.data())[i]=toupper(((char *)str.data())[i]);
    }
}

I know you're not supposed to modify that data area- आप किस डेटा क्षेत्र को संशोधित करने वाले नहीं हैं?
user93353

3
यह देर हो चुकी है, लेकिन पृथ्वी पर क्या है? उस पागल रेखा को str[i] = toupper(str[i]);पूरी तरह से ठीक से ठीक किया जा सकता है ( ठीक है, पूरी तरह से ठीक नहीं है, लेकिन यह ज्यादातर चीजों को ठीक करता है)।
क्रिस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.