ইনভেরিন্টকালচার এবং সাধারণ স্ট্রিং তুলনার মধ্যে পার্থক্য


548

সমতার জন্য সি # তে দুটি স্ট্রিং তুলনা করার সময়, ইনভারেন্টাল কালচার এবং অর্ডিনাল তুলনার মধ্যে পার্থক্য কী?



2
যারা ব্যবহার করছেন তাদের জন্য String1.Equals(String2, StringComparison.Ordinal), আপনি আরও ভাল ব্যবহার করুন String1 == String2যা অন্তর্গত String1.Equals(String2)এবং এটি ডিফল্টরূপে একটি অর্ডিনাল কেস-সংবেদনশীল তুলনা।
ঘাসন

3
@ ঘাসান নিশ্চিত নয় যে এটি =="আরও ভাল" করে কিনা, তবে এটি ক) সংক্ষিপ্ত, খ) ঠিক কী করে তা সম্পর্কে কম স্পষ্ট এবং গ) String1তুলনা ছাড়াই শূন্য হতে পারে NullReferenceException
ইউজিন বেরেসভস্কি

3
@Ghasan কর্মকর্তা দুটিই MSDN .NET ফ্রেমওয়ার্ক মধ্যে Strings ব্যবহারের সেরা পৃষ্ঠা ( msdn.microsoft.com/en-us/library/... ) overloads যে স্পষ্টভাবে উল্লেখ ব্যবহারের বিশেষ পরামর্শ দেওয়া হচ্ছে StringComparisonপ্রকার। স্ট্রিং তুলনার ক্ষেত্রে এটির অর্থ String.Equals
ওহাদ স্নাইডার

3
@EugeneBeresovsky এড়াতে NullReferenceExceptionআপনি কেবল স্ট্যাটিক পদ্ধতি ব্যবহার করতে পারেন: String.Equals(string1, string2, StringComparison.Ordinal)
ওহাদ স্নাইডার

উত্তর:


302

InvariantCulture

অক্ষর ক্রমগুলির একটি "স্ট্যান্ডার্ড" সেট ব্যবহার করে (ক, খ, সি, ... ইত্যাদি)। এটি কিছু নির্দিষ্ট লোকেলের বিপরীতে যা বিভিন্ন ক্রমে অক্ষরকে বাছাই করতে পারে ('একটি-সঙ্গে-তীব্র' লোকেলের উপর নির্ভর করে 'ক' এর আগে বা পরে হতে পারে )।

পূরণবাচক

অন্যদিকে, কাঁচা বাইট (গুলি) এর অক্ষরকে বিশুদ্ধরূপে দেখায়।


Http://msdn.microsoft.com/en-us/library/e6883c06.aspx- এ একটি দুর্দান্ত নমুনা রয়েছে যা বিভিন্ন স্ট্রিংকোপরিয়ান মানগুলির ফলাফল দেখায়। সব শেষে, এটি দেখায় (উদ্ধৃত):

StringComparison.InvariantCulture:
LATIN SMALL LETTER I (U+0069) is less than LATIN SMALL LETTER DOTLESS I (U+0131)
LATIN SMALL LETTER I (U+0069) is less than LATIN CAPITAL LETTER I (U+0049)
LATIN SMALL LETTER DOTLESS I (U+0131) is greater than LATIN CAPITAL LETTER I (U+0049)

StringComparison.Ordinal:
LATIN SMALL LETTER I (U+0069) is less than LATIN SMALL LETTER DOTLESS I (U+0131)
LATIN SMALL LETTER I (U+0069) is greater than LATIN CAPITAL LETTER I (U+0049)
LATIN SMALL LETTER DOTLESS I (U+0131) is greater than LATIN CAPITAL LETTER I (U+0049)

আপনি দেখতে পাচ্ছেন যে যেখানে ইনভারেন্টাল কালচার ফলন হয় (U + 0069, U + 0049, U + 00131), সাধারণ ফলন (U + 0049, U + 0069, U + 00131)।


25
সাধারণ তুলনা কোড পয়েন্টগুলিতে দেখায় , বাইটগুলি না।
জোয়

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

18
এমএসডিএন.মাইক্রোসফট.ইন- ইউএস / লিবারি/ms230117%28v=vs.90%29.aspx দেখুন এবং লক্ষ্য করুন যে স্ট্রিং নরমালাইজেশন এবং সাধারণ তুলনা করার পরামর্শ দেওয়া হচ্ছে।
এমপিভ্লাক

23
অর্ডিনাল অনেক দ্রুত
ড্যারেন

9
সি # স্ট্রিং তুলনা পরীক্ষাগুলি প্রকাশিত ভাল পারফরম্যান্স পরীক্ষার ফলাফল রয়েছে যা প্রতিটি পৃথক স্ট্রিং তুলনা পদ্ধতি এবং তাদের সময়ের কার্যকারিতা জানায়।
কুমার সি

259

উদাহরণস্বরূপ - এটি একটি বিষয় যা চরিত্র সম্প্রসারণ বলা হয়

var s1 = "Strasse";
var s2 = "Straße";

s1.Equals(s2, StringComparison.Ordinal);           //false
s1.Equals(s2, StringComparison.InvariantCulture);  //true

সঙ্গে InvariantCultureএস এস চরিত্র SS প্রসারিত হয়।


1
এই জিনিস এছাড়াও মধ্যে কোনো না কোনোভাবে আলাদা Ordinalএবং InvariantCulture? মূল প্রশ্নটি এটাই।
ম্যাথিজ ওয়েজেল

3
যারা জানেন না তাদের জন্য ßএটি লক্ষ্য করা উচিত যে ßজার্মানিতে কমপক্ষে একটি ডাবল সমান, উত্স: en.wikedia.org/wiki/%C3%9F
পিটার

19
এটি @ পিটারটি একেবারেই সঠিক নয়, আপনি জার্মান ßএবং আন্তঃদেশীয়ভাবে ব্যবহার করতে পারবেন না ss(আমি দেশীয় স্পিকার)। উভয় আইনী (তবে প্রায়শই একটি পুরানো / প্রস্তাবিত নয়) ক্ষেত্রে এমন একটি মামলা রয়েছে যেখানে কেবল একটির ফর্মের অনুমতি রয়েছে।
enzi

5
এই সাধারণ উদাহরণটি 2 টি তুলনার মধ্যে পার্থক্য পরিষ্কারভাবে দেখায়। আমি মনে করি আমি এখন এটি পাচ্ছি।
ব্রায়ানলেগ

4
এটি চেষ্টা করে দেখতে হয়েছিল : আদর্শ one.com/j8DvDo এত দুর্দান্ত! জার্মান ভাষায়ও একটি ছোট পাঠ। এখন ß এবং ss এর মধ্যে কী পার্থক্য রয়েছে তা ভাবছেন ...
Mzn

111

.NET ফ্রেমওয়ার্কে স্ট্রিংগুলি ব্যবহার করার জন্য সেরা অনুশীলনের দিকে ইশারা :

  • সংস্কৃতি-অজ্ঞাত স্ট্রিং মিলের জন্য আপনার নিরাপদ ডিফল্ট হিসাবে তুলনা করুন StringComparison.Ordinalবা StringComparison.OrdinalIgnoreCaseব্যবহার করুন ।
  • আরও ভাল পারফরম্যান্সের সাথে StringComparison.Ordinalবা তুলনামূলক ব্যবহার করুন StringComparison.OrdinalIgnoreCase
  • ভাষা তুলনামূলকভাবে অপ্রাসঙ্গিক (চিহ্ন হিসাবে, উদাহরণস্বরূপ) যখন স্ট্রিং অপারেশনের পরিবর্তে স্ট্রিং অপারেশনের পরিবর্তে অ-ভাষাগত StringComparison.Ordinalবা StringComparison.OrdinalIgnoreCaseমানগুলি ব্যবহার করুন CultureInfo.InvariantCulture

এবং পরিশেষে:

  • StringComparison.InvariantCultureবেশিরভাগ ক্ষেত্রে ভিত্তিতে স্ট্রিং অপারেশন ব্যবহার করবেন না । কিছু ব্যতিক্রমগুলির মধ্যে একটি হ'ল আপনি যখন ভাষাগত দিক থেকে অর্থপূর্ণ কিন্তু সাংস্কৃতিকভাবে অজ্ঞাব্য উপাত্তটি চালিয়ে যাচ্ছেন।

56

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

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

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

উদাহরণস্বরূপ, অর্ডিনাল দ্বারা: "0" < "9" < "A" < "Ab" < "Z" < "a" < "aB" < "ab" < "z" < "Á" < "Áb" < "á" < "áb"

এবং ইনভেয়ারেন্ট কালচার দ্বারা: "0" < "9" < "a" < "A" < "á" < "Á" < "ab" < "aB" < "Ab" < "áb" < "Áb" < "z" < "Z"


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

31

যদিও প্রশ্নটি সাম্যতা সম্পর্কে , দ্রুত চাক্ষুষ রেফারেন্সের জন্য, এখানে কয়েকটি আইড্রিয়েন্স্রেসিগুলি চিত্রিত করে কয়েকটি সংস্কৃতি ব্যবহার করে কিছু স্ট্রারের ক্রম সাজানো হয়েছে

Ordinal          0 9 A Ab a aB aa ab ss Ä Äb ß ä äb      
IgnoreCase       0 9 a A aa ab Ab aB ss ä Ä äb Äb ß      
--------------------------------------------------------------------
InvariantCulture 0 9 a A  ä Ä aa ab aB Ab äb Äb ss ß     
IgnoreCase       0 9 A a  Ä ä aa Ab aB ab Äb äb ß ss     
--------------------------------------------------------------------
da-DK            0 9 a A  ab aB Ab ss ß ä Ä äb Äb aa     
IgnoreCase       0 9 A a  Ab aB ab ß ss Ä ä Äb äb aa     
--------------------------------------------------------------------
de-DE            0 9 a A  ä Ä aa ab aB Ab äb Äb ß ss     
IgnoreCase       0 9 A a  Ä ä aa Ab aB ab Äb äb ss ß     
--------------------------------------------------------------------
en-US            0 9 a A  ä Ä aa ab aB Ab äb Äb ß ss     
IgnoreCase       0 9 A a  Ä ä aa Ab aB ab Äb äb ss ß     
--------------------------------------------------------------------
ja-JP            0 9 a A  ä Ä aa ab aB Ab äb Äb ß ss     
IgnoreCase       0 9 A a  Ä ä aa Ab aB ab Äb äb ss ß     

পর্যবেক্ষণ:

  • de-DE, ja-JPএবং en-USএকইভাবে বাছাই করুন
  • Invariantউপরের তিনটি সংস্কৃতি থেকে কেবল বিভিন্ন ধরণের ssএবং ßআলাদা
  • da-DK বেশ ভিন্নভাবে সাজান
  • IgnoreCaseসব নমুনা সংস্কৃতির জন্য তা পতাকাঙ্কিত বিষয়

উপরের টেবিলটি তৈরি করতে ব্যবহৃত কোড:

var l = new List<string>
    { "0", "9", "A", "Ab", "a", "aB", "aa", "ab", "ss", "ß",
      "Ä", "Äb", "ä", "äb", "あ", "ぁ", "ア", "ァ", "A", "亜" };

foreach (var comparer in new[]
{
    StringComparer.Ordinal,
    StringComparer.OrdinalIgnoreCase,
    StringComparer.InvariantCulture,
    StringComparer.InvariantCultureIgnoreCase,
    StringComparer.Create(new CultureInfo("da-DK"), false),
    StringComparer.Create(new CultureInfo("da-DK"), true),
    StringComparer.Create(new CultureInfo("de-DE"), false),
    StringComparer.Create(new CultureInfo("de-DE"), true),
    StringComparer.Create(new CultureInfo("en-US"), false),
    StringComparer.Create(new CultureInfo("en-US"), true),
    StringComparer.Create(new CultureInfo("ja-JP"), false),
    StringComparer.Create(new CultureInfo("ja-JP"), true),
})
{
    l.Sort(comparer);
    Console.WriteLine(string.Join(" ", l));
}

1
হুমমম - ঠিক আছে, আপনি এই গবেষণাটি করেছেন তা খুব ভাল এবং আপনার অনুসন্ধানগুলি পোস্ট করেছেন, যদিও আপনার বক্তব্যটি আমি ঠিক জানি না। যাইহোক, ড্যানিশ সম্ভবত "অন্যতম গুরুত্বপূর্ণ সংস্কৃতি" হতে পারে না (যদিও ৫ মিলিয়ন ড্যানস আসলে তাদের সংস্কৃতির প্রতি অনুরাগী) তবে আপনি যদি "এএ" কে অতিরিক্ত পরীক্ষার স্ট্রিং হিসাবে ফেলে দেন এবং "দা-ডি কে" হিসাবে অতিরিক্ত পরীক্ষা সংস্কৃতি, আপনি কিছু আকর্ষণীয় ফলাফল দেখতে পাবেন।
রেনিপেট

1
@ রেনিপেট তার জন্য ধন্যবাদ আমি ড্যানিশ যুক্ত করেছি, কারণ এটি ব্যবহৃত 3 টি অন্যান্য সংস্কৃতির তুলনায় একেবারে আলাদাভাবে সাজানো। (বিদ্রূপের ইঙ্গিতকারী ইমোটিকনগুলি যেমনটি ইংরেজী ভাষা পাঠের ওয়েবে অনুধাবন করা হয়েছিল তেমন ভালভাবে বোঝা যাচ্ছে না বলে আমি "সর্বাধিক গুরুত্বপূর্ণ সংস্কৃতি" মন্তব্যটি সরিয়ে দিয়েছি। সর্বোপরি, ছাত্রলীগটি CultureComparerআমরা ব্যবহার করতে পারি নি যাচাই করতে। এই টেবিলটির জন্য, Danishসংস্কৃতি (তথ্য) খুব গুরুত্বপূর্ণ হয়ে
উঠেছে

1
ধন্যবাদ। আমি বুঝতে পেরেছিলাম যে আপনার "সর্বাধিক গুরুত্বপূর্ণ সংস্কৃতি" মন্তব্যটি নুনের দানা নিয়ে নেওয়া হয়েছিল - এটি কেবলমাত্র ইমোটিকনগুলি ব্যবহার করার জন্য আমার বয়স খুব বেশি হয়েছে। আমি অনুভব করেছি যে পাঠ্যদান এতটাই সাধারণ হয়ে উঠেছে যে ইমোটিকনগুলি ব্যবহার করা আপনার রসিকতাগুলি বলার পরে ব্যাখ্যা করার মতো, যে কেউ হাসেন বা না করুক নির্বিশেষে। ঘটনাক্রমে, অন্যান্য স্ক্যান্ডিনেভিয়ান সংস্কৃতি (ফিনিশ, নরওয়েজিয়ান এবং সুইডিশ) ড্যানিশ হিসাবে একই, "আ" - র খুব বিশেষ পরিচালনা পরিচালনা বাদ দিয়ে - যা প্রমাণ করে যে ড্যানিশ অবশ্যই উন্নত সংস্কৃতি।
রেনিপেট

1
ড্যানিশ তার মূল্যবান কিসের জন্য এবং হ'ল আলাদাভাবে আলাদা আলাদা অক্ষরের অবস্থানের কারণে written (এএ), ø (ওএ, ö), এবং å (এএ, ä) লিখিত ক্রমের বর্ণমালা শেষে রয়েছে।
অ্যালেকার

26

ইনভেরেন্ট একটি ভাষাগতভাবে উপযুক্ত ধরণের তুলনা।
অর্ডিনাল একটি বাইনারি ধরণের তুলনা। (দ্রুত)
দেখুন http://www.siao2.com/2004/12/29/344136.aspx


5

এখানে উদাহরণ রয়েছে যেখানে ইনভারিয়ান্টকালচারআইগনরেস কেস এবং অর্ডিনালআইগনোরকেস ব্যবহার করে স্ট্রিং সমতা তুলনা একই ফলাফল দেয় না:

string str = "\xC4"; //A with umlaut, Ä
string A = str.Normalize(NormalizationForm.FormC);
//Length is 1, this will contain the single A with umlaut character (Ä)
string B = str.Normalize(NormalizationForm.FormD);
//Length is 2, this will contain an uppercase A followed by an umlaut combining character
bool equals1 = A.Equals(B, StringComparison.OrdinalIgnoreCase);
bool equals2 = A.Equals(B, StringComparison.InvariantCultureIgnoreCase);

আপনি যদি এটি চালনা করেন, সমান 1 মিথ্যা হবে, এবং 2 সমান হবে সত্য।


কেবল একই অনুরূপ উদাহরণ যুক্ত করতে তবে স্ট্রিং আক্ষরিক সাথে যদি a="\x00e9"(ই তীব্র) এবং b="\x0065\x0301"(ই তীব্র উচ্চারণের সাথে মিলিত হয়) StringComparer.Ordinal.Equals(a, b)মিথ্যা StringComparer.InvariantCulture.Equals(a, b)প্রত্যাবর্তন করে সত্য ফিরে আসবে।
জর্জ হেলিয়ার

2

পার্থক্যটি দেখানোর জন্য অভিনব ইউনিকোড চর এক্সম্যাপলগুলি ব্যবহার করার দরকার নেই। এখানে আজ পাওয়া যায় এমন একটি সাধারণ উদাহরণ যা অবাক করার মতো, কেবলমাত্র ASCII অক্ষর নিয়ে।

এএসসিআইআই টেবিল অনুসারে, 0(0x48) সাধারণ তুলনায় _(0x95) এর চেয়ে ছোট । ইনভায়ারেন্ট কালচার বিপরীতটি বলবে (নীচে পাওয়ারশেল কোড):

PS> [System.StringComparer]::Ordinal.Compare("_", "0")
47
PS> [System.StringComparer]::InvariantCulture.Compare("_", "0")
-1

-7

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


3
যদি আপনার সফ্টওয়্যারটি বিভিন্ন সংস্কৃতি ব্যবহার করে না, তবে এটি অর্ডিনালের তুলনায় অনেক ধীর।
কাইল

4
আমি ডাউনভোটিং বিবেচনা করেছি কারণ আপনি অবশ্যই আপনার উদ্বেগের প্রতিক্রিয়াটি ভাবেন নি। যদিও এর মধ্যে রয়েছে সত্যের দানা। যদি আপনার অ্যাপ্লিকেশনটি একাধিক সংস্কৃতির মধ্যে ব্যাপকভাবে ছড়িয়ে পড়ে ... তবে এটি অবশ্যই আপনার "সর্বদা ইনভেন্টারিটালচার ব্যবহার করার চেষ্টা করুন" এর শুরুর শব্দটির নিশ্চয়তা দেয় না, তাই না? আমি অবাক হয়েছি যে আপনি ডাউনওয়েট প্রাপ্তির পরে এবং এই বুদ্ধিটি সম্পাদনের জন্য বছরের পর বছর ধরে ফিরে আসেন নি এবং সম্ভবত আরও অভিজ্ঞতা।
সুমেরে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.