Std :: স্ট্রিংকে লোয়ার কেসে রূপান্তর করবেন কীভাবে?


777

আমি একটি std::stringছোট হাতের মধ্যে রূপান্তর করতে চান । আমি ফাংশন সম্পর্কে সচেতন tolower(), যদিও অতীতে আমার এই ফাংশনটি নিয়ে সমস্যা ছিল এবং এটি কোনওভাবেই আদর্শ নয় কারণ এটি ব্যবহারের সাথে std::stringপ্রতিটি চরিত্রের পুনরাবৃত্তি প্রয়োজন।

বিকল্প আছে যা সময়ের 100% কাজ করে?


34
আপনি কীভাবে কোনও তালিকার প্রতিটি উপাদানকে তালিকার মাধ্যমে পুনরাবৃত্তি না করে অন্য কোনও কিছুতে রূপান্তর করবেন? একটি স্ট্রিং কেবলমাত্র অক্ষরের একটি তালিকা, যদি আপনাকে প্রতিটি চরিত্রের জন্য কিছু ফাংশন প্রয়োগ করতে হয় তবে আপনার স্ট্রিংটির মাধ্যমে পুনরাবৃত্তি করতে হবে। কোন উপায় না।

14
এই প্রশ্নটি কেন ঠিক রেটিং ডাউন করে? আমার স্ট্রিং দিয়ে পুনরাবৃত্তি করতে আমার সমস্যা নেই, তবে আমি জিজ্ঞাসা করছি টোলভার (), টপার্পার () ইত্যাদি ব্যতীত অন্য কোনও কার্য রয়েছে কিনা
কনরাড

3
আপনার যদি সি স্টাইলের চর অ্যারে থাকে, তবে আমি অনুমান করি আপনি একবারে 4 টি অক্ষরকে ছোট হাতের অক্ষরে রূপান্তর করতে 4 অক্ষরের প্রতিটি ব্লকে অক্স20202020 যুক্ত করতে পারবেন (তারা ইতিমধ্যে সমস্ত বড় হয়ে থাকে)।

13
@ ড্যান: যদি তারা ইতিমধ্যে ছোট হাতের অক্ষর হতে পারে তবে অবশ্যই এজেড বা এজেড হয় তবে আপনি যোগ করার পরিবর্তে 0x20 দিয়ে বা করতে পারেন। এগুলি-স্মার্ট এটি সম্ভবত-বোবা আশাবাদগুলির মধ্যে একটি যা প্রায়শই এটির জন্য উপযুক্ত নয় ...
স্টিভ

4
আমি জানি না কেন এটি নিচে ভোট হয়েছে ... অবশ্যই এটি কিছুটা অদ্ভুতভাবে বলা হয়েছে (কারণ আপনাকে প্রতিটি আইটেমটি কোনওভাবে পুনরাবৃত্তি করতে হবে) তবে এটি বৈধ প্রশ্ন
ওয়ারেন

উত্তর:


904

এত ঘন ঘন জিজ্ঞাসিত প্রশ্ন থেকে গৃহীত :

#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); });

আপনি প্রতিটি চরিত্রের মাধ্যমে পুনরাবৃত্তি না করে সত্যই দূরে সরে যাচ্ছেন না। চরিত্রটি ছোট হাতের বা অন্যথায় বড় হাতের কিনা তা জানার কোনও উপায় নেই।

আপনি যদি সত্যিই ঘৃণা করেন তবে tolower()এখানে একটি বিশেষায়িত এএসসিআইআই বিকল্প রয়েছে যা আমি আপনাকে ব্যবহার করার পরামর্শ দিচ্ছি না:

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()কেবলমাত্র প্রতি-একক-বাইট-চরিত্রের প্রতিস্থাপন করতে পারে, যা অনেক স্ক্রিপ্টের জন্য উপযুক্ত নয়, বিশেষত যদি ইউটিএফ -8 এর মতো মাল্টি-বাইট-এনকোডিং ব্যবহার করে।


25
(পুরানো এটি হতে পারে, প্রশ্নে থাকা অ্যালগোরিদমগুলি খুব কম পরিবর্তিত হয়েছে) @ স্টিফান মাই: এসটিএল অ্যালগরিদমকে কল করার ক্ষেত্রে "ধরণের প্রচুর ওভারহেড" কী জাতীয়? ফাংশনগুলি বরং হেলান (অর্থাত্ লুপগুলির জন্য সহজ) এবং প্রায়শই ইনলাইন করা হয় কারণ একই সংকলনের ইউনিটে একই টেম্পলেট পরামিতিগুলির সাথে আপনার ফাংশনটিতে খুব কম কল রয়েছে।
eq-

257
আপনি যখনই অক্ষরগুলিকে ASCII অনুমান করেন ততবারই Godশ্বর একটি বিড়ালছানা হত্যা করেন। :(
ব্রায়ান গর্ডন

13
আপনার প্রথম উদাহরণ সম্ভাব্য হয়েছে অনির্ধারিত আচরণ (ক্ষণস্থায়ী charথেকে ::tolower(int)।) আপনি তা নিশ্চিত করতে একটি নেতিবাচক মান পাস না প্রয়োজন।
জুয়ানচোপাঞ্জা

37
-1 এর ব্যবহারটি ::tolowerক্র্যাশ হতে পারে, এটি নন-এসসিআইআই ইনপুটটির জন্য ইউবি B
চিয়ার্স এবং এইচটিএইচ - আলফ

7
বাহ্যতম নামের জায়গাতে রয়েছে তা বোঝাতে টোলভারের আগে :: :: দরকার is আপনি যদি এই কোডটি অন্য কোনও নেমস্পেসে ব্যবহার করেন তবে টোলভারের আলাদা (সম্ভবত সম্পর্কিত নয়) সংজ্ঞা থাকতে পারে যা :: ছাড়া পছন্দনীয়ভাবে নির্বাচিত হওয়ার অবসান ঘটাতে পারে।
চার্লস অফরিয়া

320

বুস্ট এর জন্য একটি স্ট্রিং অ্যালগরিদম সরবরাহ করে :

#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);

2
আমি ধরে নিই যে এএসসিআইআই ইনপুট দিয়ে টোলভারের মতো একই সমস্যা হয় নি?
পৌল

19
নন-এএসসিআইআই -7 এর জন্য ব্যর্থ।
দেবসোলার

1
এটির স্থানবিহীন সংস্করণ আছে কি?
রায়

5
@ রে, হ্যাঁto_lower_copy
স্মাক 89

233

TL; ড

আইসিইউ লাইব্রেরি ব্যবহার করুন । আপনি যদি তা না করেন তবে আপনার রূপান্তর রুটিনটি এমন নীতিগুলির সাথে নীরবে ভেঙে যাবে আপনি সম্ভবত বিদ্যমান সম্পর্কে অবগত নন।


প্রথমে আপনাকে একটি প্রশ্নের উত্তর দিতে হবে: আপনার এনকোডিংটি কী std::string? এটি কি আইএসও -8859-1? অথবা সম্ভবত আইএসও -8859-8? নাকি উইন্ডোজ কোডপেজ 1252? আপনি উপরের থেকে লোকেসকে রূপান্তর করতে যা ব্যবহার করছেন তা কি জানেন? (বা এটি চরিত্রগুলির জন্য খারাপভাবে ব্যর্থ হয়েছে 0x7f?)

আপনি যদি std::stringকনটেইনার হিসাবে ইউটিএফ -8 (8-বিট এনকোডিংগুলির মধ্যে একমাত্র বুদ্ধিমান পছন্দ) ব্যবহার করে থাকেন তবে আপনি ইতিমধ্যে নিজেকে এমন কোনও নিয়ন্ত্রণে রাখছেন তা বিশ্বাস করে নিজেকে ফাঁকি দিচ্ছেন, কারণ আপনি কোনও ধারকটিতে মাল্টিবাইট চরিত্রের ক্রমটি সংরক্ষণ করছেন are এটি মাল্টিবাইট ধারণা সম্পর্কে অবগত নয়। এমনকি সহজ কিছু এমনকি .substr()একটি টিকিং সময়স্রোত। (কারণ একটি মাল্টবাইট সিকোয়েন্স বিভক্ত করার ফলে একটি অবৈধ (উপ-) স্ট্রিং হবে)

এবং যত তাড়াতাড়ি আপনার মত কিছু করার চেষ্টা করুন std::toupper( 'ß' ), এ কোন এনকোডিং, আপনি গভীর কষ্ট হয়। (কারণ স্ট্যান্ডার্ড লাইব্রেরি দিয়ে এই "সঠিক" করা সহজভাবে সম্ভব নয়, যা কেবল এখানে প্রয়োজনীয় ফলাফল নয় কেবল একটি ফলাফলের অক্ষর সরবরাহ করতে পারে "SS")) [1] আরেকটি উদাহরণ হতে পারে std::tolower( 'I' ), যা লোকেলের উপর নির্ভর করে বিভিন্ন ফলাফল অর্জন করবে । জার্মানিতে, 'i'সঠিক হবে; তুরস্কে, 'ı'(ল্যাটিন ছোট ছোট ডটলস আই) প্রত্যাশিত ফলাফল (যা আবার ইউটিএফ -8 এনকোডিংয়ে এক বাইটের বেশি)। তবুও আরেকটি উদাহরণ হ'ল গ্রীক সিগমা , বড় '∑'হাতের অক্ষর , ছোট হাতের অক্ষর 'σ'... একটি শব্দের শেষে বাদে যেখানে এটি রয়েছে 'ς'

সুতরাং, যে কোনও ক্ষেত্রে রূপান্তর যা একবারে কোনও চরিত্রের উপরে কাজ করে বা আরও খারাপ, একবারে বাইট , ডিজাইন দ্বারা ভেঙে যায়।

তারপরে বিন্দুটি রয়েছে যে স্ট্যান্ডার্ড লাইব্রেরি, এটি করতে সক্ষম তার উপর নির্ভর করে আপনার সফ্টওয়্যারটি যে মেশিনে চলছে সেটিতে কোন লোকেলগুলি সমর্থনযোগ্য তা নির্ভর করে ... এবং যদি তা না হয় তবে আপনি কী করবেন?

তাই কি আপনি হয় সত্যিই খুঁজছেন একটি স্ট্রিং বর্গ যে সব এই সঙ্গে সঠিকভাবে আচরণ করতে সক্ষম হয়, এবং সেটা হল না কোন std::basic_string<>রূপের

(সি ++ 11 নোট: std::u16stringএবং std::u32stringহয় ভাল ।, কিন্তু এখনও নিখুঁত নয় সি ++ 20 আনা std::u8string, কিন্তু এই সব করতে এনকোডিং উল্লেখ অনেক অন্যান্য ক্ষেত্রেই তারা এখনও ইউনিকোড বলবিজ্ঞান অজ্ঞ থাকা, নিয়মমাফিককরণ, কোলেশন মতো ..। ।)

বুস্ট যদিও দেখায় জ্ঞানী সুন্দর এপিআই, Boost.Locale মূলত কাছাকাছি একটি লেফাফা হয় আইসিইউতাহলে বুস্ট হয় কম্পাইল আইসিইউ সমর্থনে ... যদি তা না হয়, Boost.Locale লোকেল সমর্থন মান লাইব্রেরির জন্য কম্পাইল সীমাবদ্ধ।

এবং আমার বিশ্বাস, পেয়ে সঙ্গে আইসিইউ একটি বাস্তব ব্যথা কখনো কখনো হতে পারে কম্পাইল করার বুস্ট। (উইন্ডোজের জন্য কোনও পূর্ব-সংকলিত বাইনারি নেই, সুতরাং আপনার অ্যাপ্লিকেশনের সাথে আপনার সেগুলি সরবরাহ করতে হবে এবং এটি পোকার সম্পূর্ণ নতুন ক্যান খুলবে ...)

সুতরাং ব্যক্তিগতভাবে আমি ঘোড়ার মুখ থেকে সরাসরি ইউনিকোড সমর্থন এবং আইসিইউ লাইব্রেরি সরাসরি ব্যবহার করার পরামর্শ দেব :

#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++ -Wall example.cpp -licuuc -licuio

এটি দেয়:

ὀδυσσεύς

নোট করুন যে শব্দের মাঝখানে Σ <->। রূপান্তরকরণ এবং শব্দের শেষে-<->। রূপান্তর। কোনও <algorithm>ভিত্তিযুক্ত সমাধান আপনাকে তা দিতে পারে না।


[1] 2017 সালে, জার্মান অর্থোগ্রাফির কাউন্সিল রায় দিয়েছে যে "ẞ" U + 1E9E ল্যাটিন ক্যাপিটাল লেটার শর্ট এস সরকারীভাবে ব্যবহার করা যেতে পারে, যেমন পাসপোর্টগুলিতে অস্পষ্টতা এড়াতে "এসএস" রূপান্তরের পাশাপাশি বিকল্প হিসাবে (যেখানে নাম মূলধনযুক্ত) )। আমার সুন্দর নজরে উদাহরণস্বরূপ, কমিটির সিদ্ধান্ত দ্বারা অপ্রচলিত ...


19
এটি সাধারণ ক্ষেত্রে সঠিক উত্তর। মানটি "এএসসিআইআই" ব্যতীত মিথ্যা ও প্রতারণা ব্যতীত অন্য কিছু পরিচালনা করার জন্য কিছুই দেয় না। এটি আপনাকে ভাবিয়ে তোলে যে আপনি সম্ভবত ইউটিএফ -16 এর সাথে ডিল করতে পারেন, তবে আপনি পারবেন না। যেমন এই উত্তরটি বলেছে, আপনি নিজের ইউনিকোড হ্যান্ডলিং না করে আপনি কোনও ইউটিএফ -16 স্ট্রিংয়ের সঠিক অক্ষরের দৈর্ঘ্য (বাইট-দৈর্ঘ্য নয়) পেতে পারবেন না। আপনার যদি সত্যিকারের পাঠ্যের সাথে ডিল করতে হয় তবে আইসিইউ ব্যবহার করুন। ধন্যবাদ, @ ডেডসোলার
সীমিত প্রায়শ্চিত্ত

আইবিইউ কি উবুন্টু / উইন্ডোজে ডিফল্টরূপে উপলব্ধ বা পৃথকভাবে ইনস্টল করা দরকার? এছাড়াও এই উত্তরটি সম্পর্কে কীভাবে: stackoverflow.com/a/35075839/207661 ?
শীতল শাহ

1
এই, দেখুন, একটি বাস্তব উত্তর! আমাকে সরাসরি সরাসরি নির্দেশ করার জন্য ধন্যবাদ দেবসোলার।
ড্যান বেচার্ড

2
@ ডেভসোলার সম্মত! দৈর্ঘ্যের ধারণাটি পাঠ্যের পরিবর্তে অর্থহীন (আমরা অপরাধীদের তালিকায় লিগচারগুলি যুক্ত করতে পারি)। এতে বলা হয়েছে, যেহেতু লোকেরা একটি দৈর্ঘ্যের একক গ্রহণের জন্য ট্যাব এবং নিয়ন্ত্রণ করতে ব্যবহৃত হয়, তাই কোড পয়েন্টগুলি আরও স্বজ্ঞাত ব্যবস্থা হবে measure ওহ, এবং সঠিক উত্তর দেওয়ার জন্য ধন্যবাদ, এটি এতদূর নিচে দেখে দুঃখ হয়েছে :-(
মাসার্স

3
@ এলএফ প্রান্তিকভাবে আরও ভাল। তবে এখনও অনেক কিছুই coveredাকা হয়নি: toupperএবং tolowerএখনও একক অক্ষরগুলিতে কাজ করে। স্ট্রিং ক্লাসটির এখনও স্বাভাবিককরণের কোনও ধারণা নেই (যেমন "" ü "" ডায়ারিসিস সহ ইউ "বা" ইউ + সংমিশ্রণ ডায়ারেসিস "হিসাবে এনকোড করা আছে) বা যেখানে স্ট্রিং পৃথক হতে পারে বা নাও হতে পারে। তালিকাটি এগিয়ে যায়। u8string (অন্যান্য স্ট্যান্ডার্ড স্ট্রিং ক্লাসগুলির মতো) "মধ্য দিয়ে যাওয়ার" জন্য উপযুক্ত। তবে আপনি যদি ইউনিকোড প্রক্রিয়া করতে চান তবে আপনার আইসিইউ দরকার
দেবসোলার

36

সি ++ 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);
}

9
তবে, একটি ফরাসি মেশিনে, এই প্রোগ্রামটি ফরাসি ভাষায় অনুমোদিত নন ASCII অক্ষরগুলিকে রূপান্তর করে না। উদাহরণস্বরূপ একটি স্ট্রিং 'টেস্ট স্ট্রিং 123'। Test Ï \ n 'রূপান্তরিত হবে:' পরীক্ষার স্ট্রিং 123। É Ï \ n 'যদিও অক্ষর É Ï এবং তাদের নিম্ন কেস কাউন্টার্পার্টস' é 'এবং' ï ', ফরাসি ভাষায় অনুমোদিত। মনে হচ্ছে এটির কোনও সমাধান এই থ্রেডের অন্যান্য বার্তাগুলির দ্বারা সরবরাহ করা হয়নি।
উত্থাপন করে

আমি মনে করি এর জন্য আপনার একটি সঠিক লোকেল সেট করা দরকার।
ব্যবহারকারী 1095108

@ সংশ্লেষ, এরপরে কেউ আইসিইউ সম্পর্কে একটি উত্তর পোস্ট করেছেন এবং এটি অবশ্যই যাওয়ার উপায়। অন্যান্য সমাধানগুলির চেয়ে সহজ যা লোকেলটি বোঝার চেষ্টা করবে।
অ্যালেক্সিস উইলক

আমি ব্যক্তিগত, ব্যক্তিগতভাবে সম্ভব হলে বাহ্যিক গ্রন্থাগার ব্যবহার না করা পছন্দ করতাম।
kayleeFrye_onDeck

31

যদি স্ট্রিংটিতে ASCII ব্যাপ্তির বাইরে UTF-8 অক্ষর থাকে, তবে :: আলগোরিদম :: টু-ব্লোয়ারগুলিকে রূপান্তর করবে না। ইউটিএফ -8 জড়িত থাকাকালীন সর্বোত্তম ব্যবহারের বুস্ট :: লোকেল :: টু ব্লোয়ার Http://www.boost.org/doc/libs/1_51_0/libs/locale/doc/html/conversions.html দেখুন


15

এটি স্টিফান মাইয়ের প্রতিক্রিয়াটির ফলোআপ: আপনি যদি রূপান্তরটির ফলাফলটিকে অন্য স্ট্রিংয়ে রাখতে চান তবে ফোন করার আগে আপনাকে তার স্টোরেজ স্পেসটি প্রাক-বরাদ্দ করতে হবে std::transform। যেহেতু এসটিএল গন্তব্য পুনরাবৃত্তকারীগুলিতে অক্ষরগুলি রুপান্তরিত করে (লুপের প্রতিটি পুনরাবৃত্তিতে এটি বৃদ্ধি করে), গন্তব্য স্ট্রিংটি স্বয়ংক্রিয়ভাবে পুনরায় আকার দেওয়া হবে না এবং আপনি মেমোরি স্টমপিংয়ের ঝুঁকিপূর্ণ।

#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;
}

1
এটি আমার জন্য Ä তে
res

ম্যানুয়াল রাইজাইজের পরিবর্তে এখানে একটি পিছনের প্রবেশকারী পুনরুক্তি ব্যবহার করতে পারে।
চিলি

11

রেফারেন্স ভেরিয়েবলের সাথে লুপের উপর ভিত্তি করে ব্যাপ্তি ব্যবহার করে অন্য একটি পদ্ধতি

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

cout<<test<<endl;

6

আমি যতদূর দেখি বুস্ট লাইব্রেরিগুলি সত্যই খারাপ পারফরম্যান্স ভিত্তিক। আমি তাদের অর্ডারযুক্ত_ম্যাপটি এসটিএলে পরীক্ষা করেছি এবং এটি গড়ে 3 গুণ ধীর ছিল (সেরা কেস 2, সবচেয়ে খারাপটি 10 ​​গুণ ছিল)। এছাড়াও এই অ্যালগরিদমটি খুব কম দেখাচ্ছে।

পার্থক্যটি এত বড় যে আমি নিশ্চিত যে tolower"আপনার প্রয়োজনের জন্য" এটি উত্সাহের সমান করতে আপনার যা যা করা দরকার তা বৃদ্ধির চেয়ে দ্রুততর হবে ।

আমি একটি অ্যামাজন ইসি 2 এ এই পরীক্ষাগুলি করেছি, সুতরাং পরীক্ষার সময় পারফরম্যান্সে ভিন্নতা থাকলেও আপনি এখনও এই ধারণাটি পেতে পারেন।

./test
Elapsed time: 12365milliseconds
Elapsed time: 1640milliseconds
./test
Elapsed time: 26978milliseconds
Elapsed time: 1646milliseconds
./test
Elapsed time: 6957milliseconds
Elapsed time: 1634milliseconds
./test
Elapsed time: 23177milliseconds
Elapsed time: 2421milliseconds
./test
Elapsed time: 17342milliseconds
Elapsed time: 14132milliseconds
./test
Elapsed time: 7355milliseconds
Elapsed time: 1645milliseconds

-O2 এটি এটি তৈরি:

./test
Elapsed time: 3769milliseconds
Elapsed time: 565milliseconds
./test
Elapsed time: 3815milliseconds
Elapsed time: 565milliseconds
./test
Elapsed time: 3643milliseconds
Elapsed time: 566milliseconds
./test
Elapsed time: 22018milliseconds
Elapsed time: 566milliseconds
./test
Elapsed time: 3845milliseconds
Elapsed time: 569milliseconds

সূত্র:

string str;
bench.start();
for(long long i=0;i<1000000;i++)
{
    str="DSFZKMdskfdsjfsdfJDASFNSDJFXCKVdnjsafnjsdfjdnjasnJDNASFDJDSFSDNJjdsanjfsdnfjJNFSDJFSD";
    boost::algorithm::to_lower(str);
}
bench.end();

bench.start();
for(long long i=0;i<1000000;i++)
{
    str="DSFZKMdskfdsjfsdfJDASFNSDJFXCKVdnjsafnjsdfjdnjasnJDNASFDJDSFSDNJjdsanjfsdnfjJNFSDJFSD";
    for(unsigned short loop=0;loop < str.size();loop++)
    {
        str[loop]=tolower(str[loop]);
    }
}
bench.end();

আমার অনুমান একটি উত্সর্গীকৃত মেশিনে পরীক্ষা করা উচিত তবে আমি এই ইসি 2 ব্যবহার করব তাই আমার মেশিনে এটি পরীক্ষা করার দরকার নেই।


1
সংকলন করার সময় আপনি কী অপ্টিমাইজেশন অপশনগুলি খুললেন? আমি ভাবছি উচ্চতর অপ্টিমাইজেশন স্তরের সাথে এসটিএল ভারী উত্সাহাগুলি আরও ভাল চালানো উচিত।
ওয়েই গান

1
আমি পরীক্ষার একটিতে -O2 ব্যবহার করেছি, আর কিছুই নয়।
ইথেরিয়লোনে

2
আনর্ডারড_ম্যাপের পারফরম্যান্স হ্যাশিং অ্যালগরিদম আপনার ব্যবহার করা ডেটার সাথে মিলিত করে depends এমন একটি ম্যাজিক হ্যাশিং অ্যালগরিদম নেই যা আনর্ডার্ডড_ম্যাপটিকে যত তাড়াতাড়ি সম্ভব করতে সমস্ত এবং যে কোনও ডেটার জন্য কাজ করে। বেঞ্চমার্ক এবং বিভিন্ন জিনিস চেষ্টা করুন। আপনি খারাপ পারফরম্যান্স পাওয়ার কারণ, হ্যাশটির সাহায্যে আপনি প্রচুর সংঘর্ষ পাচ্ছেন যা মূলত একটি তালিকার মধ্যে অনুসন্ধানের কারণ। আরও তথ্যের জন্য এই সাইটটি দেখুন: fgda.pl/post/7/gcc-hash-map-vs-unordered-map আমার উদ্দেশ্যে, লিঙ্কে সরবরাহিত ফাংশনটি সংঘর্ষ হ্রাস করেছে এবং এইভাবে খুব দ্রুত ছিল।
leetNightshade

6

স্ট্যান্ডিং নেমস্পেস সম্পর্কে বিরক্ত না করে স্ট্রিংকে লোয়ারকেসে রূপান্তর করার সহজ উপায়টি নীচে রয়েছে

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;
}

5

std::ctype::tolower()মানক সি ++ স্থানীয়করণ লাইব্রেরি থেকে আপনার জন্য এটি সঠিকভাবে করবে। এখানে টোলভার রেফারেন্স পৃষ্ঠা থেকে উত্তোলিত একটি উদাহরণ দেওয়া হয়েছে

#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";
}

দুর্দান্ত, যতক্ষণ আপনি অক্ষরে অক্ষরে রূপান্তর করতে পারেন। যদি আপনার উত্স স্ট্রিং হয় const? এটি এটিকে কিছুটা আরও অগোছালো বলে মনে হচ্ছে (যেমন আপনি ব্যবহার করতে পারেন এমনটি মনে হচ্ছে না f.tolower()), কারণ আপনাকে অক্ষরগুলি একটি নতুন স্ট্রিংয়ে রাখা দরকার। আপনি কি অপারেটরের জন্য transform()কিছু ব্যবহার করবেন std::bind1st( std::mem_fun() )?
কুজার

একটি কনস্টিং স্ট্রিংয়ের জন্য, আমরা কেবল একটি স্থানীয় অনুলিপি তৈরি করতে পারি এবং তারপরে এটি জায়গায় রূপান্তর করতে পারি।
সমীর

হ্যাঁ, অনুলিপি তৈরি করা আরও ওভারহেড যুক্ত করে।
কোয়াজার

আপনি std :: ctype :: টোলভার সংস্করণ দিয়ে রূপান্তর করতে পারেন যা পয়েন্টার নেয় না। পিছনে প্রবেশকারী পুনরায় আবরণকারী অ্যাডাপ্টার ব্যবহার করুন এবং এমনকি আপনার আউটপুট স্ট্রিং প্রাক-আকার দেওয়ার বিষয়ে আপনাকে চিন্তা করার দরকার নেই।
মরিচ 2

দুর্দান্ত, বিশেষত কারণ প্যারামিটারের tolowerসাথে libstdc ++ এর মধ্যে locale, অন্তর্ভুক্ত কলটি use_facetপারফরম্যান্সের বাধা হিসাবে উপস্থিত বলে মনে হচ্ছে। আমার এক সহকর্মী এমন boost::iequalsএক সংস্করণ দিয়ে প্রতিস্থাপনের মাধ্যমে (যা এই সমস্যা রয়েছে) বেশ কয়েকটি 100% গতি বৃদ্ধি পেয়েছে যেখানে use_facetকেবল একবার লুপের বাইরে বলা হয়।
আর্ন ভোগেল

3

বুস্টের বিকল্প হ'ল পোকো (পোকোপ্রজেক্ট.অর্গ)।

পোকো দুটি রূপ সরবরাহ করে:

  1. প্রথম ভেরিয়েন্টটি মূল স্ট্রিংটি পরিবর্তন না করে একটি অনুলিপি তৈরি করে।
  2. দ্বিতীয় বৈকল্পিক জায়গায় মূল স্ট্রিং পরিবর্তন করে।
    "ইনপ্লেস" সংস্করণগুলির সর্বদা নামে "ইনপ্লেস" থাকে।

উভয় সংস্করণ নীচে প্রদর্শিত হয়:

#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);

3

পরীক্ষা করেও আপার কেস কে নিম্নে রূপান্তর করার একটি উপায় আছে এবং এটি বেশ সোজা-এগিয়ে। আইসুপার () ফাংশন / ম্যাক্রোর ক্লোকলেড ব্যবহারের সাথে আপনার অবস্থান সম্পর্কিত সমস্যাগুলির যত্ন নেওয়া উচিত, তবে যদি তা না হয় তবে আপনি সর্বদা আপনার হৃদয়ের বিষয়বস্তুতে ইউটোএল [] কে টুইট করতে পারেন।

সি এর অক্ষরগুলি সত্যিকার অর্থে মাত্র 8-বিট ইনট হয় (মুহুর্তের প্রশস্ত অক্ষরের সেটগুলি উপেক্ষা করে) আপনি একটি 256 বাইট অ্যারে তৈরি করতে পারেন যা বিকল্পের অক্ষরের একটি সেট রেখে, এবং রূপান্তর ফাংশনে আপনার স্ট্রিংয়ের অক্ষরগুলিকে সাবস্ক্রিপ হিসাবে ব্যবহার করুন রূপান্তর অ্যারে।

যদিও 1-for-1 ম্যাপিংয়ের পরিবর্তে, আপার-কেস অ্যারে সদস্যদের লো-কেসের অক্ষরের জন্য BYTE অন্তর্গত মান দিন। আপনি এখানে ইলোয়ার () এবং আইসুপার () দরকারী হতে পারেন।

এখানে চিত্র বর্ণনা লিখুন

কোডটি এর মতো দেখাচ্ছে ...

#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;
}

এই পদ্ধতিটি একই সাথে আপনাকে পরিবর্তন করতে ইচ্ছুক অন্য কোনও অক্ষরের পুনর্নির্মাণের অনুমতি দেবে।

আধুনিক প্রসেসরগুলিতে চলাকালীন এই পদ্ধতির একটি বিশাল সুবিধা রয়েছে, শাখাগুলি নিয়ে গঠিত পরীক্ষাগুলি যদি নেই তবে শাখার পূর্বাভাস দেওয়ার দরকার নেই। এটি অন্যান্য লুপগুলির জন্য সিপিইউর শাখার পূর্বাভাস যুক্তি সংরক্ষণ করে এবং পাইপলাইন স্টলগুলি রোধ করে।

ইবিসিডিককে ASCII তে রূপান্তর করতে ব্যবহৃত একই হিসাবে এখানে কিছু লোক এই পদ্ধতিকে স্বীকৃতি দিতে পারে।


2
"পরীক্ষাগুলি যদি কখনও সারণীর কথা শুনেছেন, তবে কী করে ওপরের কেস কে নিম্নে রূপান্তর করার একটি উপায় আছে?
গ্যাবার বুয়েলা

1
নেতিবাচক অক্ষরের জন্য অপরিজ্ঞাত আচরণ।
রোল্যান্ড ইলিগ

মডার্ন সিপিইউগুলি সিপিইউ নয় মেমোরিতে বাধা রয়েছে। বেঞ্চমার্কিং আকর্ষণীয় হবে।
কনটাঙ্গো

3

যেহেতু উত্তরের কোনওটিতেই আসন্ন রেঞ্জের লাইব্রেরি উল্লেখ করা হয়নি, যা সি ++ 20 সাল থেকে স্ট্যান্ডার্ড লাইব্রেরিতে পাওয়া যায় এবং বর্তমানে গিটহাবের হিসাবে পৃথক পৃথকভাবে উপলব্ধ 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>এবং প্রয়োজনীয় রেঞ্জের শিরোনামগুলি ভুলে যাবেন না ))

দ্রষ্টব্য: unsigned charল্যাম্বডায় আর্গুমেন্ট হিসাবে ব্যবহার cppreferences দ্বারা অনুপ্রাণিত , যা বলে:

অন্য সমস্ত ফাংশনের মতো <cctype>, আচরণটি std::tolowerঅপরিজ্ঞাত করা হয় যদি আর্গুমেন্টের মান না হিসাবে প্রতিনিধিত্বযোগ্য unsigned charবা সমান হয় EOF। সরল charগুলি (বা signed charগুলি) দিয়ে নিরাপদে এই ফাংশনগুলি ব্যবহার করতে , প্রথমে যুক্তিটি রূপান্তর করা উচিত unsigned char:

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

একইভাবে, পুনরাবৃত্তির মান প্রকার charবা হয় যখন এগুলি সরাসরি স্ট্যান্ডার্ড অ্যালগরিদমগুলির সাথে ব্যবহার করা উচিত নয় signed char। পরিবর্তে, মানটি 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;
}

3

আমার নিজস্ব টেম্পলেট ফাংশন যা আপার / লোয়ার কেস সম্পাদন করে।

#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 std::move(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 std::move(s2);
}

এই আমার প্রয়োজন ছিল। আমি কেবল towlowerপ্রশস্ত অক্ষরের জন্য ব্যবহার করেছি যা ইউটিএফ -16 সমর্থন করে।
জুভ

2

আপনি যদি কিছু সাধারণ চান চান তবে এখানে ম্যাক্রো কৌশল রয়েছে:

#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 অক্ষর নয়।


1
আমি যখন ম্যাক্রোগুলি দেওয়ার জন্য একেবারে ভাল সমাধানের জন্য অগ্রাহ্য করছি - আপনি এমনকি সেই সমাধানগুলি দেন।
ক্লিয়ারার

2
ম্যাক্রো টেকনিকটির অর্থ এমন কোনও কিছুর জন্য কোডের কম টাইপ করা যা প্রোগ্রামিংয়ে সাধারণত কেউ প্রচুর ব্যবহার করতে পারেন। কেন ব্যবহার করবেন না? নাহলে ম্যাক্রো কেন আদৌ আছে?
ভলমাইক

3
ম্যাক্রোস সি থেকে প্রাপ্ত একটি উত্তরাধিকার যা পরিত্রাণ পেতে কঠোর পরিশ্রম করা হচ্ছে। আপনি যদি টাইপের পরিমাণ হ্রাস করতে চান তবে কোনও ফাংশন বা ল্যাম্বডা ব্যবহার করুন। void strtoupper(std::string& x) { std::transform (x.begin(), x.end(), x.begin(), ::toupper); }
ক্লিয়ারার

1
@ ক্লেয়ার যেমন আমি আরও ভাল কোডার হতে চাই, আপনি কি আমাকে এমন কোনও এএনএসআই ডক লিঙ্ক সরবরাহ করতে পারেন যেখানে কোনও এএনএসআই সি ++ কমিটি "সি ++ থেকে ম্যাক্রো থেকে মুক্তি পাওয়ার জন্য একটি সভা আহ্বান করা দরকার"? নাকি অন্য কোনও রোডম্যাপ?
ভলমাইক

2
না, পারছি না। যদিও এই বিষয়ে বেশিরভাগ ক্ষেত্রে বর্জনীর অবস্থান সম্পর্কে স্পষ্ট করে দেওয়া হয়েছে। এছাড়াও সি তে ম্যাক্রোগুলি ব্যবহার না করার প্রচুর কারণ রয়েছে পাশাপাশি সি ++ রয়েছে। xএকটি বৈধ এক্সপ্রেশন হতে পারে, এটি কেবল সঠিকভাবে সংকলন করতে ঘটে তবে ম্যাক্রোগুলির কারণে সম্পূর্ণ বোগাস ফলাফল দেবে।
ক্লিয়ারার

2
// 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/references/locale/tolower/


2

বিকল্প আছে যা সময়ের 100% কাজ করে?

না

লোয়ারকেসিং পদ্ধতি বেছে নেওয়ার আগে আপনার নিজের কাছে বেশ কয়েকটি প্রশ্ন জিজ্ঞাসা করা উচিত।

  1. স্ট্রিংটি কীভাবে এনকোড করা আছে? সরল এএসসিআইআই? হল UTF-8? বর্ধিত ASCII উত্তরাধিকার এনকোডিং কিছু ফর্ম?
  2. তবুও লোয়ার কেস বলতে কী বোঝ? ভাষার ক্ষেত্রে কেস ম্যাপিংয়ের নিয়ম আলাদা হয়! আপনি কি এমন কিছু চান যা ব্যবহারকারীদের লোকালকে স্থানীয় করা? আপনি কি এমন কিছু চান যা আপনার সফ্টওয়্যারটি চালিত সমস্ত সিস্টেমে ধারাবাহিকভাবে আচরণ করে? আপনি কি কেবলমাত্র ASCII টি অক্ষর ছোট করতে এবং সমস্ত কিছুর মধ্য দিয়ে যেতে চান?
  3. কি লাইব্রেরি পাওয়া যায়?

এই প্রশ্নের উত্তরগুলি একবার পেয়ে গেলে আপনি নিজের প্রয়োজন অনুসারে সলিউশন খুঁজতে শুরু করতে পারেন fits কোনও আকারের এমন কোনওটি ফিট করে না যা সর্বত্র যে কারও জন্য কাজ করে!


2

এই ফাংশন চেষ্টা করুন :)

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;
}

1

মাইক্রোসফট প্ল্যাটফর্মে আপনি ব্যবহার করতে পারেন 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 );
}

0

টুকিটাকি সংকেতলিপি

#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;
}


0

অনুলিপি করুন কারণ এটি উত্তরকে উন্নত করতে অস্বীকৃত ছিল। অনেক ধন্যবাদ


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সনাক্তকারী মাধ্যমে লুপের অভ্যন্তরে একটি রেফারেন্স হিসাবে উপলব্ধ c


আপনি কোথা থেকে নিজের উত্তরটি অনুলিপি করেছেন তা দয়া করে পরিষ্কার করুন।
bfontaine

0

সি ++ এর স্ট্রিংয়ের জন্য টোলভার বা টুপার পদ্ধতি প্রয়োগ করা হয়নি তবে এটি চরের জন্য উপলব্ধ। যে কোনও স্ট্রিংয়ের প্রতিটি চর সহজেই পড়তে পারে, এটিকে প্রয়োজনীয় ক্ষেত্রে রূপান্তর করতে পারে এবং এটিকে আবার স্ট্রিংয়ে রাখতে পারে। কোনও তৃতীয় পক্ষের লাইব্রেরি ব্যবহার না করে একটি নমুনা কোড:

#include<iostream>

int main(){
  std::string str = std::string("How IS The Josh");
  for(char &ch : str){
    ch = std::tolower(ch);
  }
  std::cout<<str<<std::endl;
  return 0;
}

স্ট্রিংয়ে অক্ষর ভিত্তিক ক্রিয়াকলাপের জন্য : স্ট্রিংয়ের প্রতিটি অক্ষরের জন্য


-1

বড় হাতের অক্ষরে এবং বিপরীতে বড় হাতের অক্ষরে রূপান্তর করার জন্য এটি আরও একটি সহজ সংস্করণ হতে পারে। আমি এই উত্স কোডটি সংকলন করতে ভিএস2017 সম্প্রদায় সংস্করণ ব্যবহার করেছি।

#include <iostream>
#include <string>
using namespace std;

int main()
{
    std::string _input = "lowercasetouppercase";
#if 0
    // My idea is to use the ascii value to convert
    char upperA = 'A';
    char lowerA = 'a';

    cout << (int)upperA << endl; // ASCII value of 'A' -> 65
    cout << (int)lowerA << endl; // ASCII value of 'a' -> 97
    // 97-65 = 32; // Difference of ASCII value of upper and lower a
#endif // 0

    cout << "Input String = " << _input.c_str() << endl;
    for (int i = 0; i < _input.length(); ++i)
    {
        _input[i] -= 32; // To convert lower to upper
#if 0
        _input[i] += 32; // To convert upper to lower
#endif // 0
    }
    cout << "Output String = " << _input.c_str() << endl;

    return 0;
}

দ্রষ্টব্য: যদি বিশেষ অক্ষর থাকে তবে কন্ডিশন চেক ব্যবহার করে পরিচালনা করতে হবে।


-8

আমি স্টাডি :: ট্রান্সফর্ম করার চেষ্টা করেছি, আমার কাছে সমস্ত জঘন্য স্টল ক্রাইপটিক সংকলন ত্রুটি যা ২০০ বছর আগে কেবল ড্র্রুডই বুঝতে পারে (থেকে ফ্লিবিডি ফ্ল্যাবিডি ফ্লুতে রূপান্তর করতে পারে না)

এটি সূক্ষ্মভাবে কাজ করে এবং সহজেই টুইট করা যায়

string LowerCase(string s)
{
    int dif='a'-'A';
    for(int i=0;i<s.length();i++)
    {
        if((s[i]>='A')&&(s[i]<='Z'))
            s[i]+=dif;
    }
   return s;
}

string UpperCase(string s)
{
   int dif='a'-'A';
    for(int i=0;i<s.length();i++)
    {
        if((s[i]>='a')&&(s[i]<='z'))
            s[i]-=dif;
    }
   return s;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.