কিভাবে একটি স্ট্রিং আপার কেস রূপান্তর করতে পারে। গুগলিং থেকে আমি যে উদাহরণগুলি পেয়েছি তার মধ্যে কেবল চরগুলিই ডিল করতে হবে।
কিভাবে একটি স্ট্রিং আপার কেস রূপান্তর করতে পারে। গুগলিং থেকে আমি যে উদাহরণগুলি পেয়েছি তার মধ্যে কেবল চরগুলিই ডিল করতে হবে।
উত্তর:
স্ট্রিং অ্যালগোরিদম বুস্ট করুন:
#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
। কোন ধারনা?
সি ++ 11 এবং টুপার () ব্যবহার করে সংক্ষিপ্ত সমাধান।
for (auto & c: str) c = toupper(c);
c
হবে না const char
(থেকে auto
)? যদি তা হয় তবে আপনি এটিকে ( const
অংশের কারণে ) যা দিয়ে ফিরে আসবে তা নির্ধারণ করতে পারবেন না toupper(c)
।
c
করার unsigned char
জন্য কাস্ট করা প্রয়োজন।
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 নাল-টার্মিনেটেড সিকোয়েন্স ইউটিলিটিগুলি
এই শিরোলেখগুলির বিষয়বস্তু স্ট্যান্ডার্ড সি লাইব্রেরির শিরোনামগুলির মতো হবে <ctype.h>, <wctype.h>, <স্ট্রিং h>, <wchar.h>, এবং <stdlib.h> [...]
যার অর্থ এই যে cctype
সদস্যরা স্ট্যান্ডার্ড অ্যালগরিদমে সরাসরি ব্যবহারের জন্য উপযুক্ত নয়।
একই উদাহরণের সাথে আর একটি সমস্যা হ'ল এটি আর্গুমেন্টটি দেয় না বা যাচাই করে না যে এটি অ-নেতিবাচক; এটি সাদামাটা char
স্বাক্ষরিত সিস্টেমগুলির জন্য বিশেষত বিপজ্জনক । (কারণ হ'ল: যদি এটি ম্যাক্রো হিসাবে প্রয়োগ করা হয় তবে এটি সম্ভবত একটি সারণীতে একটি সারণী এবং আপনার যুক্তি সূচি ব্যবহার করবে A নেতিবাচক সূচী আপনাকে ইউবি দেবে))
এএসসিআইআই অক্ষর সেটটির জন্য এই সমস্যাটি সিমডের সাহায্যে ভেক্টরাইজযোগ্য ।
-O3 -march=native
একটি কোর 2 ডিউও (মেরম) এ x86-64 গিসি 5.2 সহ প্রাথমিক পরীক্ষা করা । 120 অক্ষরের একই স্ট্রিং (মিশ্র লোয়ারकेস এবং নন-লোয়ারকেস এএসসিআইআই) 40M বারে লুপে রূপান্তরিত হয়েছে (কোনও ক্রস-ফাইল ইনলাইনিং সহ নয়, তাই সংকলকটি লুপের বাইরে অপ্টিমাইজ করতে বা এর কোনওটিকে উত্তোলন করতে পারে না)। একই উত্স এবং গন্তব্য বাফার, সুতরাং কোনও ম্যালোক ওভারহেড বা মেমরি / ক্যাশে প্রভাব নেই: পুরো সময় L1 ক্যাশে ডেটা গরম থাকে এবং আমরা খালি সিপিইউ-আবদ্ধ।
boost::to_upper_copy<char*, std::string>()
: 198.0s । হ্যাঁ, উবুন্টু 15.10 এ 1.58 বুস্ট করা সত্যই এই ধীর। আমি একটি ডিবাগারে asm প্রফুল্ল করেছি এবং একক পদক্ষেপ নিয়েছি এবং এটি সত্যই, সত্যিই খারাপ: চরিত্র অনুসারে লোকাল ভেরিয়েবলের গতিশীল_কাস্ট রয়েছে !!! (ডায়নামিক_কাস্ট একাধিক কলকে স্ট্রম্পে ক্যাম্পে নিয়ে যায়)। এর সাথে LANG=C
ও সাথে ঘটেLANG=en_CA.UTF-8
।
আমি স্ট্যান্ড :: স্ট্রিং ব্যতীত অন্য কোনও রেঞ্জটি ব্যবহার করে পরীক্ষা করিনি। হতে পারে অন্য রূপটিto_upper_copy
আরও ভালতর করতে পারে তবে আমি মনে করি এটি অনুলিপি new
/ malloc
অনুলিপিটির জন্য সর্বদা স্থান থাকবে তাই এটি পরীক্ষা করা আরও কঠিন। হতে পারে আমি যা কিছু করেছি সেগুলি সাধারণ ব্যবহারের ক্ষেত্রে থেকে আলাদা হয় এবং সাধারণত বন্ধ হওয়া জি ++ প্রতি চরিত্রের লুপের বাইরে লোকাল সেটআপ স্টাফ উত্তোলন করতে পারে। আমার থেকে লুপ পড়া এবং একটি std::string
লেখার char dstbuf[4096]
জন্য পরীক্ষার জন্য বোধগম্য।
লুপ কলিং গ্লিবসিtoupper
: 6.67 এস ( int
যদিও সম্ভাব্য মাল্টি-বাইট ইউটিএফ -8 এর ফলাফল পরীক্ষা করছে না , তুর্কিদের জন্য এটি গুরুত্বপূর্ণ matters)
cmov
, যাইহোক L1 তে টেবিল গরম থাকে।যখন কোনও লোকেল সেট করা হয় তখন উইন্ডোতে ধীর হওয়া সম্পর্কে এই প্রশ্নটিtoupper()
দেখুন ।
আমি হতবাক হয়ে গিয়েছিলাম যে বুস্টটি অন্যান্য বিকল্পগুলির চেয়ে ধীর গতির একটি ক্রম। আমি -O3
সক্ষম হয়েছি কিনা ডাবল-চেক করেছিলাম এবং এমনকি এটি কী করছে তা দেখার জন্য এএসএমকে একক পদক্ষেপ দিয়েছিল। এটি ঝাঁকুনির সাথে প্রায় একই গতি ++ 3.8। প্রতি-চরিত্রের লুপের ভিতরে এটির বিশাল ওভারহেড রয়েছে। perf record
/ report
ফলাফলের (জন্য cycles
জন্য perf ঘটনা) হল:
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% ...
যখন পুনরাবৃত্তির গণনাটি লুপের আগে জানা যায় তখনই জিসিসি এবং ক্ল্যাং কেবল লুপগুলিকে স্বয়ংক্রিয়-ভেক্টরাইজ করবে। (যেমন, এর সরল-সি প্রয়োগের মতো লুপগুলি অনুসন্ধান করুনstrlen
স্বয়ংক্রিয়করণ করবে না))
সুতরাং, ক্যাশে ফিট করার জন্য পর্যাপ্ত ছোট স্ট্রিংগুলির জন্য, আমরা স্ট্রিংগুলির জন্য একটি গুরুত্বপূর্ণ স্পিডআপ পাই ~ 128 অক্ষর strlen
প্রথমে করা থেকে দীর্ঘ । সুস্পষ্ট দৈর্ঘ্যের স্ট্রিংগুলির জন্য এটি প্রয়োজন হবে না (যেমন সি ++ 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;
}
যে কোনও শালীন libc একটি দক্ষ হবে strlen
এর যা একবারে বাইট লুপিংয়ের চেয়ে অনেক দ্রুত, তাই পৃথক ভেক্টরাইজড স্ট্রেন এবং টপার্প লুপগুলি দ্রুত।
বেসলাইন: একটি লুপ যা ফ্লাইতে 0 টি সমাপ্তির জন্য পরীক্ষা করে।
40M পুনরাবৃত্তির জন্য টাইমস, একটি কোর 2 (মেরম) 2.4GHz এ। জিসিসি 5.2 -O3 -march=native
। (উবুন্টু 15.10)। dst != src
(সুতরাং আমরা একটি অনুলিপি তৈরি করি), তবে সেগুলি ওভারল্যাপ করে না (এবং কাছাকাছি নয়)। দুটোই সারিবদ্ধ
কিছু ফলাফল ঝাঁকুনির সাথে কিছুটা আলাদা।
ফাংশনটি কল করে এমন মাইক্রোবেঞ্চমার্ক লুপটি একটি পৃথক ফাইলে রয়েছে। অন্যথায় এটি ইনলাইনস এবংstrlen()
লুপ থেকে উত্তোলন হয়ে যায় এবং এটি নাটকীয়ভাবে দ্রুত চালিত হয়, esp। 16 চর স্ট্রিং (0.187s) এর জন্য।
এর বড় সুবিধাটি হ'ল যে কোনও আর্কিটেকচারের জন্য জিসিসি এটি স্বয়ংক্রিয়ভাবে ভেক্টরাইজ করতে পারে, তবে বড় অসুবিধাটি এটি ছোট স্ট্রিংয়ের সাধারণত-সাধারণ ক্ষেত্রে ধীর হয়।
সুতরাং এখানে বড় স্পিডআপ রয়েছে তবে সংকলক স্বয়ং-ভেক্টরাইজেশন দুর্দান্ত কোড তৈরি করে না, এসএসপি। শেষ পর্যন্ত 15 অক্ষর পরিষ্কার করার জন্য।
আমার কেস-ফ্লিপ ফাংশনের ভিত্তিতে যা প্রতিটি বর্ণমালার চরিত্রের ক্ষেত্রে উল্টায়। এটি "স্বাক্ষরযুক্ত স্বীকৃতি তুলনা কৌশল" এর সুবিধা নেয়, যেখানে আপনি low < a && a <= high
পরিসীমা স্থানান্তর করে একক স্বাক্ষরযুক্ত তুলনা না করে করতে পারেন , যাতে কোনও মানের চেয়ে বেশি যে low
মোড়কের চেয়ে কম হয় high
। (এটি কাজ করে যদি low
এবংhigh
খুব বেশী দূরে সরাইয়া হয় না।)
এসএসইতে কেবল একটি স্বাক্ষরিত তুলনা-বৃহত্তর রয়েছে, তবে আমরা এখনও স্বাক্ষরিত রেঞ্জের নীচে সীমা স্থানান্তর করে "স্বাক্ষরযুক্ত তুলনা" কৌশলটি ব্যবহার করতে পারি: 'এ' + 128 বিয়োগ করুন, সুতরাং বর্ণানুক্রমিক অক্ষরগুলি -128 থেকে -128 এর মধ্যে রয়েছে +25 (-128 + 'জেড' - 'এ')
মনে রাখবেন যে 128 যোগ করা এবং 128 বিয়োগ করা 8 বিট পূর্ণসংখ্যার জন্য একই জিনিস। বহন করার জন্য কোথাও নেই, সুতরাং এটি কেবলমাত্র জোর (বহনযোগ্য অ্যাড), উচ্চ বিটকে ফ্লিপ করে।
#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
}
একটি ভেক্টরের জন্য কাজ করে এমন ফাংশনটি দেওয়া, একটি সম্পূর্ণ স্ট্রিং প্রক্রিয়া করার জন্য আমরা এটিকে একটি লুপে কল করতে পারি। যেহেতু আমরা ইতিমধ্যে এসএসই 2 কে লক্ষ্য করছি, আমরা একই সাথে একটি ভেক্টরাইজড এন্ড-অফ-স্ট্রিং চেক করতে পারি।
16 বি এর ভেক্টর করার পরে আমরা শেষ অবধি আপ 15 টু 15 বাইটের "ক্লিনআপ" এর জন্য আরও অনেক কিছু করতে পারি: আপার-কেসিং আদর্শবান, তাই কিছু ইনপুট বাইটগুলি পুনরায় প্রক্রিয়া করা ভাল is আমরা উত্সের সর্বশেষ 16 বি এর একটি স্বাক্ষরবিহীন লোড করি এবং লুপ থেকে শেষ 16 বি স্টোরকে ওভারল্যাপ করে ডেস্ট বাফারে সংরক্ষণ করি।
পুরো স্ট্রিংটি 16 বি এর নিচে থাকা অবস্থায় এটি কেবল কার্যকর হয় না: এমনকি যখন dst=src
অ-পারমাণবিক পঠন-সংশোধন-লিখন কিছু বাইটকে স্পর্শ না করার মতো জিনিস হয় না এবং বহুবিধিত কোডটি ভেঙে ফেলতে পারে।
আমাদের এটির জন্য একটি স্কেলার লুপ রয়েছে, এবং src
সারিবদ্ধ হওয়ার জন্যও । যেহেতু আমরা জানি না যে 0 টি সমাপ্তিটি কোথায় হবে, তাই থেকে একটি স্বাক্ষরবিহীন লোড src
পরবর্তী পৃষ্ঠায় এবং সেগফল্টে যেতে পারে। যদি আমাদের কোনও প্রান্তিক 16 বি অংশে কোনও বাইটের দরকার হয় তবে পুরো সারিবদ্ধ 16 বি অংশটি লোড করা সর্বদা নিরাপদ।
ফুল উৎস: একটি 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;
}
40M পুনরাবৃত্তির জন্য টাইমস, একটি কোর 2 (মেরম) 2.4GHz এ। জিসিসি 5.2 -O3 -march=native
। (উবুন্টু 15.10)। dst != src
(সুতরাং আমরা একটি অনুলিপি তৈরি করি), তবে সেগুলি ওভারল্যাপ করে না (এবং কাছাকাছি নয়)। দুটোই সারিবদ্ধ
(আসলে _mm_store
লুপের সাথে সময়সীমা _mm_storeu
বেঁধে দেওয়া হয়নি , কারণ ঠিকানাটি সারিবদ্ধ হওয়ার পরেও মেরুতে স্টোরু ধীরে ধীরে Ne এটি নেহালেম এবং পরে ঠিক আছে copy অনুলিপি ঠিক করার পরিবর্তে আমি কোডটি এখনকার হিসাবে রেখেছি কিছু ক্ষেত্রে 0 সমাপ্তি, কারণ আমি সবকিছুকে পুনরায় সময় দিতে চাই না))
সুতরাং 16 বি এর চেয়ে দীর্ঘ সংক্ষিপ্ত স্ট্রিংয়ের জন্য, এটি অটো-ভেক্টরাইজডের চেয়ে নাটকীয়ভাবে দ্রুত। একটি ভেক্টর-প্রস্থের চেয়ে এক-কম-দৈর্ঘ্যের দৈর্ঘ্য কোনও সমস্যা উপস্থাপন করে না। স্টোর-ফরওয়ার্ডিং স্টলের কারণে ইন-প্লেস পরিচালনা করার সময় এগুলির সমস্যা হতে পারে। (তবে মনে রাখবেন যে মূল ইনপুটের পরিবর্তে আমাদের নিজস্ব আউটপুট প্রক্রিয়াজাতকরণ এটি ঠিক আছে, কারণ ট্রিপার আদর্শবান)।
পার্শ্ববর্তী কোডটি কী চায় এবং টার্গেট মাইক্রোআরকিটেকচারের উপর নির্ভর করে বিভিন্ন ব্যবহারের ক্ষেত্রে এটি টিউন করার প্রচুর সুযোগ রয়েছে। ক্লিনআপ অংশের জন্য দুর্দান্ত কোড নির্গমনের জন্য সংকলকটি পাওয়া কঠিন। ব্যবহার ffs(3)
(যা বিএসএফ অথবা x86 উপর tzcnt করার প্রনয়ন) ভাল হবে বলে মনে হয়, কিন্তু বিট একটি প্রয়োজন স্পষ্টত যে পুনরায় মনে যেহেতু আমি (দেখুন FIXME মন্তব্য) এই উত্তরটি অধিকাংশ আপ লেখার পর একটি বাগ লক্ষ্য।
এমনকি ছোট স্ট্রিং জন্য ভেক্টর speedups সঙ্গে প্রাপ্ত করা যাবে movq
বা movd
লোড / দোকান। আপনার ব্যবহারের ক্ষেত্রে প্রয়োজন হিসাবে কাস্টমাইজ করুন।
আমাদের ভেক্টরের যখন উচ্চ বিট সেট সহ কোনও বাইট থাকে তখন আমরা সনাক্ত করতে পারি এবং সেই ক্ষেত্রে সেই ভেক্টরের জন্য একটি স্কেলার utf-8-সচেতন লুপে ফিরে যেতে পারি। dst
বিন্দু তুলনায় বিভিন্ন পরিমাণ দ্বারা আগাম পারেন src
পয়েন্টার, কিন্তু একবার আমরা ফিরে একটি প্রান্তিককৃত পেতে src
পয়েন্টার, আমরা এখনও ঠিক unaligned ভেক্টর দোকানে চেষ্টা করবো dst
।
UTF-8, তবে বেশিরভাগ UTF-8 এর ASCII উপসেট সমন্বিত পাঠ্যের জন্য, এটি ভাল হতে পারে: সব ক্ষেত্রে সঠিক আচরণের সাথে সাধারণ ক্ষেত্রে উচ্চ কার্যকারিতা। যখন অ-এএসসিআইআই প্রচুর আছে, সম্ভবত এটি সমস্ত সময় স্কেলারের ইউটিএফ -8 সচেতন লুপে থাকার চেয়ে আরও খারাপ হবে though
অন্যান্য ভাষার ব্যয়ে দ্রুত ইংরাজী করা ভবিষ্যতের প্রুফ সিদ্ধান্ত নয় যদি ডাউনসাইডটি তাৎপর্যপূর্ণ হয়।
তুর্কী লোকেলে ( tr_TR
), থেকে সঠিক ফলাফলের toupper('i')
হয় 'İ'
(U0130), না 'I'
(সাধারণ হওয়া ASCII)। উইন্ডোজটিতে ধীরগতির বিষয়ে একটি প্রশ্নে মার্টিন বোনারের মন্তব্য দেখুন tolower()
।
মাল্টি-বাইট ইউটিএফ 8 ইনপুট অক্ষরের মতো আমরা সেখানে স্কেলারের ব্যতিক্রম-তালিকা এবং ফলব্যাকের জন্যও পরীক্ষা করতে পারি।
এই অনেক জটিলতার সাথে, এসএসই 4.2 PCMPISTRM
বা কোনও কিছু আমাদের চেকগুলি একসাথে করতে সক্ষম হতে পারে।
আপনার স্ট্রিং এএসসিআইআই বা আন্তর্জাতিক অক্ষর আছে?
যদি এটি পরবর্তী ক্ষেত্রে হয় তবে "বড় হাতের অক্ষর" এতটা সহজ নয়, এবং এটি ব্যবহৃত বর্ণমালার উপর নির্ভর করে। দ্বি দ্বিদলীয় এবং একতাত্ত্বিক বর্ণমালা রয়েছে। আপার এবং লোয়ার কেসগুলির জন্য কেবল দ্বিদলীয় বর্ণমালার আলাদা আলাদা অক্ষর রয়েছে। এছাড়াও, ল্যাটিন মূলধন 'ডিজেড' (\ u01F1 'ডিজেড') এর মতো সংমিশ্রিত অক্ষর রয়েছে যা তথাকথিত শিরোনাম কেস ব্যবহার করে । এর অর্থ হ'ল কেবল প্রথম অক্ষর (ডি) পরিবর্তিত হয়।
আমি আপনাকে আইসিইউতে সন্ধান করার পরামর্শ দিচ্ছি এবং সহজ এবং সম্পূর্ণ কেস ম্যাপিংয়ের মধ্যে পার্থক্য রাখছি । এটি সাহায্য করতে পারে:
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);
আপনি যদি কেবলমাত্র এসসিআইআই অক্ষর ব্যবহার করেন তবে দ্রুততর :
for(i=0;str[i]!=0;i++)
if(str[i]<='z' && str[i]>='a')
str[i]-=32;
দয়া করে নোট করুন যে এই কোডটি দ্রুত চালিত হয় তবে কেবল ASCII এ কাজ করে এবং এটি একটি "বিমূর্ত" সমাধান নয়।
আপনার যদি ইউনিকোড সমাধান বা আরও প্রচলিত এবং বিমূর্ত সমাধানের প্রয়োজন হয় তবে অন্যান্য উত্তরের জন্য যান এবং সি ++ স্ট্রিংয়ের পদ্ধতিতে কাজ করুন।
C++
তবে আপনি C
এখানে একটি উত্তর লিখেছিলেন । (আমি
'
?
যতক্ষণ না আপনি কেবলমাত্র ASCII- এর সাথে ভাল থাকেন এবং আপনি আরডাব্লু মেমরির জন্য একটি বৈধ পয়েন্টার সরবরাহ করতে পারেন, সিতে একটি সহজ এবং খুব কার্যকর ওয়ান-লাইনার রয়েছে:
void strtoupper(char* str)
{
while (*str) *(str++) = toupper((unsigned char)*str);
}
এটি ASCII শনাক্তকারীদের মতো সাধারণ স্ট্রিংগুলির জন্য বিশেষত ভাল যা আপনি একই চরিত্রের ক্ষেত্রে স্বাভাবিক করতে চান। তারপরে আপনি স্টাফ: স্ট্রিংয়ের উদাহরণটি তৈরি করতে বাফারটি ব্যবহার করতে পারেন।
//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());
এটি গ্লোবাল টুপার ফাংশন ব্যবহার করে এমন সমস্ত উত্তরের চেয়ে আরও ভাল পারফরম্যান্স করবে এবং সম্ভবত: টু_পারটি নীচে যা করছে তা বাড়িয়ে তুলবে।
এটি কারণ: :: টুপারকে লোকেলটি সন্ধান করতে হবে - কারণ এটি একটি ভিন্ন থ্রেড দ্বারা পরিবর্তিত হতে পারে - প্রতিটি অনুরোধের জন্য, যদিও এখানে কেবল লোকালে () কল করার জন্য এই শাস্তি রয়েছে। এবং লোকেল সন্ধানের মধ্যে সাধারণত একটি লক নেওয়া জড়িত।
আপনি অটো প্রতিস্থাপন করার পরে, নতুন অ-কনস্ট্রেন্ট স্ট্রিংডাটা () ব্যবহার করে এবং টেমপ্লেটটি বন্ধ করার জন্য ""> ">>") এর মতো স্থান যুক্ত করার পরে এটি সি ++ 98 এর সাথেও কাজ করে:
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
।
সি ++ 11 সহ সর্বশেষ কোডটি এখানে
std::string cmd = "Hello World";
for_each(cmd.begin(), cmd.end(), [](char& in){ in = ::toupper(in); });
toupper
সংখ্যার সাথে ডাকা হলে এই কোডটি অনির্ধারিত আচরণের ডাক দেয়।
উত্তর এর @dirkgently খুব দীপক হয়, কিন্তু আমি যে জোর উদ্বেগ কারণে যেমন নিম্নে দেখানো হল চাই,
অন্য সমস্ত ফাংশনের মতো, স্টাড :: টুপারের আচরণ অপরিজ্ঞাত করা হয় যদি আর্গুমেন্টের মান স্বাক্ষরযুক্ত চর হিসাবে না ইওএফ এর সমান হয়। সরল অক্ষর (বা স্বাক্ষরিত অক্ষর) দিয়ে নিরাপদে এই ফাংশনগুলি ব্যবহার করতে, যুক্তিটি প্রথমে স্বাক্ষরবিহীন অক্ষরে রূপান্তর করা উচিত
রেফারেন্স : স্ট্যান্ড :: টুপার
এর সঠিক ব্যবহারটি হওয়া 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
সংখ্যার সাথে ডাকা হলে এই কোডটি অনির্ধারিত আচরণের ডাক দেয়।
আমার সমাধান (আলফার জন্য 6th ষ্ঠ বিট সাফ করা):
#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 টি বিট চরিত্রের সাথে সম্পর্কিত হন (যা মিলান বাবুস্কভ বাদে অন্য সমস্ত উত্তরও ধরে নেয়) আপনি রূপক ব্যবহার করে সংকলনের সময় একটি লক-আপ টেবিল তৈরি করে দ্রুত গতি পেতে পারেন। আইডোন.কম এ লাইব্রেরি ফাংশনের চেয়ে 7x দ্রুত এবং একটি হাতের লিখিত সংস্করণ ( http://ideone.com/sb1Rup ) এর চেয়ে 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;
}
আমি এই সমাধানটি ব্যবহার করি। আমি জানি যে আপনি সেই ডেটা অঞ্চলটি পরিবর্তন করার কথা বলছেন না .... তবে আমি মনে করি এটি বেশিরভাগ বাফার ওভাররন বাগ এবং নাল চরিত্রের জন্য .... উপরের কেসিং জিনিসগুলি একই নয়।
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
সম্ভবত এটি এসসিআইআই অনুমান করা হয়।