कोई स्ट्रिंग को अपर केस में कैसे बदल सकता है। गुग्लिंग से जो उदाहरण मुझे मिले हैं, उन्हें केवल छंद से निपटना है।
कोई स्ट्रिंग को अपर केस में कैसे बदल सकता है। गुग्लिंग से जो उदाहरण मुझे मिले हैं, उन्हें केवल छंद से निपटना है।
जवाबों:
बूस्ट स्ट्रिंग एल्गोरिदम:
#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");
std::string newstr(boost::to_upper_copy<std::string>("Hello World"));
#include <algorithm>
#include <string>
std::string str = "Hello World";
std::transform(str.begin(), str.end(),str.begin(), ::toupper);
toupper()
मैक्रो के रूप में लागू किया जा सकता है। यह एक समस्या का कारण हो सकता है।
toupper
। कोई विचार?
C ++ 11 और टॉपर () का उपयोग करते हुए लघु समाधान।
for (auto & c: str) c = toupper(c);
c
की हो const char
(प्रकार auto
)? यदि ऐसा है, तो आप इसे ( const
भाग के कारण ) असाइन नहीं कर सकते हैं कि क्या लौटाया गया है toupper(c)
।
c
करने के लिए कलाकारों की जरूरत unsigned char
के लिए यह corred किया जाना है।
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
पर हस्ताक्षर किए गए हैं। (इसका कारण: यदि इसे एक मैक्रो के रूप में लागू किया जाता है तो यह संभवतः एक लुकअप टेबल का उपयोग करेगा और आपके तर्क उस तालिका में अनुक्रमित करेंगे। एक नकारात्मक सूचकांक आपको यूबी देगा।)
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 के लिए परिणाम की जांच नहीं करना , हालांकि यह तुर्की के लिए मायने रखता है।)
cmov
, वैसे भी L1 में टेबल गर्म है।स्थानीय स्तर पर सेट होने पर विंडोज पर धीमा होने के बारे में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% ...
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
(इसलिए हम एक प्रति बनाते हैं), लेकिन वे ओवरलैप नहीं करते हैं (और पास नहीं हैं)। दोनों गठबंधन कर रहे हैं।
क्लैंग के साथ कुछ परिणाम थोड़े अलग हैं।
फ़ंक्शन को कॉल करने वाला माइक्रोबेनमार्क लूप एक अलग फ़ाइल में है। अन्यथा यह सुर्खियों में है औरstrlen()
लूप से बाहर हो जाता है, और यह नाटकीय रूप से तेज, एस्प चलाता है। 16 चार तार के लिए (0.187s)।
इसका प्रमुख लाभ यह है कि gcc इसे किसी भी आर्किटेक्चर के लिए ऑटो-वेक्टर कर सकता है, लेकिन मुख्य नुकसान यह है कि यह छोटे तारों के आमतौर पर सामान्य मामले के लिए धीमा है।
तो बड़े स्पीडअप हैं, लेकिन कंपाइलर ऑटो-वैरिफिकेशन महान कोड, एस्प नहीं बनाता है। अंतिम-से -15 वर्णों की सफाई के लिए।
मेरे केस-फ्लिप फंक्शन के आधार पर जो हर अल्फ़ाबेटिक चरित्र के मामले को प्रभावित करता है। यह "अहस्ताक्षरित तुलना चाल" का लाभ उठाता है, जहां आप 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
(इसलिए हम एक प्रति बनाते हैं), लेकिन वे ओवरलैप नहीं करते हैं (और पास नहीं हैं)। दोनों गठबंधन कर रहे हैं।
(वास्तव _mm_store
में लूप में समय के साथ , नहीं _mm_storeu
, क्योंकि स्टोरू मेरोम पर धीमी है, यहां तक कि जब पता संरेखित किया जाता है। यह नेहल्म और बाद में ठीक है। मैंने भी कोड को छोड़ दिया है-अब के लिए, कॉपी करने में विफलता को ठीक करने के बजाय। कुछ मामलों में समाप्ति 0, क्योंकि मैं सब कुछ फिर से नहीं करना चाहता।)
तो 16B से छोटे तार के लिए, यह ऑटो-वेक्टर से नाटकीय रूप से तेज़ है। लंबाई एक-से-एक-वेक्टर-चौड़ाई एक समस्या पेश नहीं करती है। स्टोर-फ़ॉरवर्डिंग स्टॉल के कारण, इन-प्लेस संचालन करते समय उन्हें समस्या हो सकती है। (लेकिन ध्यान दें कि मूल इनपुट के बजाय हमारे स्वयं के आउटपुट को संसाधित करने के लिए अभी भी ठीक है, क्योंकि टौपर बेकार है)।
अलग-अलग उपयोग-मामलों के लिए इसे ट्यूनिंग के लिए बहुत गुंजाइश है, जो आस-पास के कोड को लक्षित करता है, और लक्ष्य माइक्रोआर्किटेक्चर पर निर्भर करता है। कंपाइलर को क्लीनअप भाग के लिए अच्छा कोड प्राप्त करना मुश्किल है। का उपयोग करना ffs(3)
(जो x86 पर bsf या tzcnt को संकलित करता है) अच्छा प्रतीत होता है, लेकिन जाहिर है कि बिट को फिर से सोचने की जरूरत है क्योंकि मैंने इस उत्तर को लिखने के बाद एक बग देखा (FIXME टिप्पणियों को देखें)।
यहां तक कि छोटे तारों के लिए वेक्टर स्पीडअप movq
या movd
लोड / स्टोर के साथ प्राप्त किया जा सकता है । अपने उपयोग-मामले के लिए आवश्यकतानुसार अनुकूलित करें।
हम पता लगा सकते हैं कि जब हमारे वेक्टर में उच्च बिट सेट के साथ कोई बाइट्स होता है, और उस स्थिति में उस वेक्टर के लिए एक स्केलर 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
या कुछ एक बार में हमारी बहुत सारी जाँच करने में सक्षम हो सकता है।
क्या आपके पास तार में ASCII या अंतर्राष्ट्रीय वर्ण हैं?
यदि यह बाद का मामला है, तो "अपरकेसिंग" इतना आसान नहीं है, और यह प्रयुक्त वर्णमाला पर निर्भर करता है। द्विसदनीय और द्विसदनीय वर्णमालाएं हैं। केवल द्विसदनीय वर्णमाला में ऊपरी और निचले मामले के लिए अलग-अलग वर्ण होते हैं। इसके अलावा, मिश्रित अक्षर हैं, जैसे लैटिन कैपिटल लेटर 'DZ' (\ u01F1 'DZ') जो तथाकथित का उपयोग करते हैं शीर्षक शीर्षक का । इसका मतलब है कि केवल पहला चरित्र (डी) बदल जाता है।
मेरा सुझाव है कि आप में देखो आईसीयू में देखें , और सिंपल और फुल केस मैपिंग में अंतर करें। यह मदद कर सकता है:
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;
}
**
पहले समाधान पर मापदंडों के बाद सितारे क्या करते हैं?
**
है कि कोड सिंटैक्स में बोल्ड फ़ॉन्ट का उपयोग करने की कोशिश से बचा हुआ एक टाइपो है।
toupper
नकारात्मक संख्याओं के साथ कॉल किया जाता है तो यह कोड अपरिभाषित व्यवहार को आमंत्रित करता है।
निम्नलिखित मेरे लिए काम करता है।
#include <algorithm>
void toUpperCase(std::string& str)
{
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
}
int main()
{
std::string str = "hello";
toUpperCase(&str);
}
toupper
नकारात्मक संख्याओं के साथ कॉल किया जाता है तो यह कोड अपरिभाषित व्यवहार को आमंत्रित करता है।
एक मेमने का उपयोग करें।
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);
यदि आप केवल ASCII वर्णों का उपयोग करते हैं तो तेज़ :
for(i=0;str[i]!=0;i++)
if(str[i]<='z' && str[i]>='a')
str[i]-=32;
कृपया ध्यान दें कि यह कोड तेजी से चलता है लेकिन केवल ASCII पर काम करता है और "सार" समाधान नहीं है।
यदि आपको UNICODE समाधान या अधिक पारंपरिक और सार समाधान चाहिए, तो अन्य उत्तरों के लिए जाएं और C ++ स्ट्रिंग्स के तरीकों के साथ काम करें।
C++
, लेकिन आपने C
यहां एक उत्तर लिखा है। (मैं
'
?
जब तक आप एएससीआईआई-ओनली के साथ ठीक हैं और आप आरडब्ल्यू मेमोरी को एक वैध सूचक प्रदान कर सकते हैं, सी में एक सरल और बहुत प्रभावी एक-लाइनर है:
void strtoupper(char* str)
{
while (*str) *(str++) = toupper((unsigned char)*str);
}
यह विशेष रूप से सरल तार के लिए अच्छा है जैसे कि ASCII पहचानकर्ता जिसे आप एक ही चरित्र-मामले में सामान्य करना चाहते हैं। तब आप std: string आवृत्ति का निर्माण करने के लिए बफर का उपयोग कर सकते हैं।
//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;
}
for (size_t i = 0 ...
। इसे पढ़ने में इतनी मेहनत करने का कोई अच्छा कारण भी नहीं है। यह स्ट्रिंग को पहले कॉपी करता है और फिर उस पर लूप करता है। @ 'a'
चरित्र कांस्टेंट का फायदा नहीं उठाने के अलावा ल्यूक का जवाब कुछ मायनों में बेहतर है ।
#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());
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 );
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; }
std::string value;
for (std::string::iterator p = value.begin(); value.end() != p; ++p)
*p = toupper(*p);
toupper
नकारात्मक संख्याओं के साथ कॉल किया जाता है तो यह कोड अपरिभाषित व्यवहार को आमंत्रित करता है।
toupper()
फ़ंक्शन का प्रयास करें ( #include <ctype.h>
)। यह वर्णों को तर्क के रूप में स्वीकार करता है, तार पात्रों से बने होते हैं, इसलिए आपको प्रत्येक व्यक्तिगत चरित्र पर पुनरावृति करनी होगी, जब एक साथ रखा जाता है जिसमें तार शामिल होते हैं
toupper
नकारात्मक संख्याओं के साथ अपरिभाषित व्यवहार को आमंत्रित करता है। आपको आवश्यक कलाकारों का उल्लेख करना चाहिए unsigned char
।
यहाँ C ++ 11 के साथ नवीनतम कोड है
std::string cmd = "Hello World";
for_each(cmd.begin(), cmd.end(), [](char& in){ in = ::toupper(in); });
toupper
नकारात्मक संख्याओं के साथ कॉल किया जाता है तो यह कोड अपरिभाषित व्यवहार को आमंत्रित करता है।
जवाब के @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!
सुनिश्चित नहीं है कि कोई अंतर्निहित फ़ंक्शन है। इसे इस्तेमाल करे:
या तो 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
}
toupper
नकारात्मक संख्याओं के साथ कॉल किया जाता है तो यह कोड अपरिभाषित व्यवहार को आमंत्रित करता है।
मेरा समाधान (अल्फा के लिए 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
नकारात्मक संख्याओं के साथ कॉल किया जाता है तो यह कोड अपरिभाषित व्यवहार को आमंत्रित करता है।
इस पृष्ठ पर इन सभी समाधानों की तुलना में वे कठिन हैं जो उन्हें होना चाहिए।
यह करो
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
लूप।
याद रखें कि स्ट्रिंग का आकार सीमांकक लौटाता है इसलिए अपने लूप टेस्ट में <और नहीं <= का उपयोग करें।
आउटपुट होगा: कुछ स्ट्रिंग जो आप कनवर्ट करना चाहते हैं
tolower
लूप हैं, और उनमें से ज्यादातर मानक लूप चर नामों का उपयोग करते हैं i
, जैसे कि अजीब नहीं forLoop
।
किसी भी पुस्तकालय का उपयोग किए बिना:
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;
}
यदि आप केवल 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
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;
}
यह 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;
}
मैं इस समाधान का उपयोग करता हूं। मुझे पता है कि आप उस डेटा क्षेत्र को संशोधित करने वाले नहीं हैं .... लेकिन मुझे लगता है कि यह ज्यादातर बफर कीड़े और अशक्त चरित्र के लिए है .... ऊपरी आवरण वाली चीजें समान नहीं हैं।
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
- आप किस डेटा क्षेत्र को संशोधित करने वाले नहीं हैं?
str[i] = toupper(str[i]);
पूरी तरह से ठीक से ठीक किया जा सकता है ( ठीक है, पूरी तरह से ठीक नहीं है, लेकिन यह ज्यादातर चीजों को ठीक करता है)।
::toupper
सबसे अधिक संभावना है ASCII।