স্ট্রিংয়ের অংশটি পজিশনে কীভাবে প্রতিস্থাপন করবেন?


155

আমার এই স্ট্রিং রয়েছে: ABCDEFGHIJ

স্ট্রিংয়ের সাথে আমার অবস্থান 4 থেকে পজিশনে স্থান করতে হবে ZX

এটি দেখতে এটির মতো হবে: ABCZXFGHIJ

তবে এর সাথে ব্যবহার করার string.replace("DE","ZX")দরকার নেই - আমার অবস্থানের সাথে ব্যবহার করা দরকার

আমি এটা কিভাবে করবো?


@ টটজাম - তারিখগুলি পরীক্ষা করুন। এই এক এক আপনি লিঙ্ক চেয়ে পুরোনো নয়।
টুলমেকারস্টেভ

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

@ টটজাম - আহ, আমি সেই প্রস্তাবটি সম্পর্কে জানতাম না - এটি উল্লেখ করার জন্য ধন্যবাদ। (যদিও এটি কোনও পুরানো কিছু নতুনের সদৃশ হিসাবে প্রতিবেদন হওয়া দেখতে বিভ্রান্তিকর, তবে এই জাতীয় ক্ষেত্রে, এটি স্পষ্টভাবে ব্যাখ্যা করা উচিত যে আপনি কোনও পুরানো প্রশ্নের সদৃশ হিসাবে চিহ্নিত করছেন, কারণ লিঙ্কযুক্তটির আরও ভাল উত্তর রয়েছে))
টুলমেকারস্টিভ

উত্তর:


198

স্ট্রিংয়ের মধ্যে রেঞ্জগুলি যুক্ত করা এবং মুছে ফেলার সহজ উপায় হ'ল ব্যবহার করা StringBuilder

var theString = "ABCDEFGHIJ";
var aStringBuilder = new StringBuilder(theString);
aStringBuilder.Remove(3, 2);
aStringBuilder.Insert(3, "ZX");
theString = aStringBuilder.ToString();

একটি বিকল্প ব্যবহার করা হয় String.Substring, তবে আমি মনে করি StringBuilderকোডটি আরও পঠনযোগ্য।


6
এটি কোনও এক্সটেনশান পদ্ধতিতে মোড়ানো ভাল হবে :)
বেলেক্সান্দ্রে

আপনি এখানে স্ট্রিংবিল্ডার ব্যবহার করেন কেন? ভি 4 ভেন্ডেটের উত্তর যা খুব বেশি পঠনযোগ্য তা পরীক্ষা করে দেখুন ...
ফোর্টেগা

1
@ ফোর্তেগা সরান () এবং সন্নিবেশ () প্রতিটি তৈরি করে একটি নতুন স্ট্রিং ফিরিয়ে দেয়। স্ট্রিংবিল্ডার পদ্ধতির কোনও অতিরিক্ত বরাদ্দ মেমরির পূর্ব-বরাদ্দ বিভাগের মধ্যে কাজ করে এবং এর মধ্যে চরগুলি ঘুরিয়ে এড়াতে পারে cost
redcalx

@ রেডাক্যালাক্স এটি সত্য, তবে একটি স্ট্রিংবিল্ডার অবজেক্টটি প্রবর্তন করে এবং পাঠ্যতা হ্রাস করার মাধ্যমে একটি অতিরিক্ত ব্যয় চালু করা হয়েছে
ফোর্টেগা

2
আপনি এখানে স্ট্রিংবিল্ডার ব্যবহারের মূল বিষয় কী, যদি আপনি ভি 4 ভেন্ডেটের মতো একইভাবে সরান এবং সন্নিবেশ করান তবে তিনি সেটিকে সরাসরি স্ট্রিংয়ে করছেন? অপ্রয়োজনীয় কোড বলে মনে হচ্ছে
বিপাক

186
string s = "ABCDEFGH";
s= s.Remove(3, 2).Insert(3, "ZX");

17
আমি এটিকে নতুন স্ট্রিংবিল্ডার (...) আরম্ভ করার চেয়ে পছন্দ করি না। ধন্যবাদ!
মাইকেল নরগ্রেন

3
আমি জানি না কেন কেউ এই অপারেশনের জন্য স্ট্রিংবিল্ডার ব্যবহার করবে। এটি ভাল উত্তর
ন্যাপিং র‌্যাবট

43

রিপ্লেসএট (ইনড ইনডেক্স, ইনট দৈর্ঘ্য, স্ট্রিং প্রতিস্থাপন)

এখানে একটি এক্সটেনশন পদ্ধতি যা স্ট্রিংবিল্ডার বা সাবস্ট্রিং ব্যবহার করে না। এই পদ্ধতিটি প্রতিস্থাপনের স্ট্রিংটিকে উত্সের স্ট্রিংয়ের দৈর্ঘ্য ছাড়িয়ে যেতে দেয়।

//// str - the source string
//// index- the start location to replace at (0-based)
//// length - the number of characters to be removed before inserting
//// replace - the string that is replacing characters
public static string ReplaceAt(this string str, int index, int length, string replace)
{
    return str.Remove(index, Math.Min(length, str.Length - index))
            .Insert(index, replace);
}

এই ফাংশনটি ব্যবহার করার সময়, আপনি যদি পুরো প্রতিস্থাপনের স্ট্রিংটি যথাসম্ভব অনেকগুলি অক্ষর প্রতিস্থাপন করতে চান, তবে প্রতিস্থাপনের স্ট্রিংয়ের দৈর্ঘ্যের দৈর্ঘ্য নির্ধারণ করুন:

"0123456789".ReplaceAt(7, 5, "Hello") = "0123456Hello"

অন্যথায়, আপনি মুছে ফেলা হবে এমন অক্ষরের পরিমাণ নির্দিষ্ট করতে পারেন:

"0123456789".ReplaceAt(2, 2, "Hello") = "01Hello456789"

আপনি যদি দৈর্ঘ্য 0 হতে নির্দিষ্ট করে থাকেন তবে এই ফাংশনটি সন্নিবেশ ফাংশনটির মতোই কাজ করে:

"0123456789".ReplaceAt(4, 0, "Hello") = "0123Hello456789"

আমার ধারণা, এটি আরও কার্যকর কারণ স্ট্রিংবিল্ডার ক্লাসটি আরম্ভ করার দরকার নেই এবং যেহেতু এটি আরও বেসিক ক্রিয়াকলাপ ব্যবহার করে। আমি ভুল হলে আমাকে সংশোধন করুন। :)


5
স্ট্রিংবিল্ডার আরও কার্যকর যদি স্ট্রিংটি দীর্ঘ হয় তবে 200 টি অক্ষর বলুন।
টিম শেমলেটার

ঠিকানা নাই. সরাসরি কাজ করেছেন। ধন্যবাদ
ডি_এডেট

9

ব্যবহার করুন String.Substring()(বিশদ এখানেবাম অংশটি কাটতে ) , তারপরে আপনার প্রতিস্থাপন, তারপরে ডান অংশ। সূচিগুলি ঠিক না হওয়া পর্যন্ত খেলুন :)

কিছুটা এইরকম:

string replacement=original.Substring(0,start)+
    rep+original.Substring(start+rep.Length);

2
আমি উপরের তিনটি পদ্ধতি ব্যবহার করে তিনটি পদ্ধতি তৈরি করেছি (স্ট্রিং। রিমুভ / ইনসার্ট, স্ট্রিংবিল্ডার। রিমু / সন্নিবেশ এবং ড্যানিয়েলের সাবস্ট্রিং উত্তর, এবং সাবস্ট্রিং ছিল দ্রুততম পদ্ধতি।
ফ্রান্সিনে দেগ্রোড টেলর

7

এক্সটেনশন পদ্ধতি হিসাবে।

public static class StringBuilderExtension
{
    public static string SubsituteString(this string OriginalStr, int index, int length, string SubsituteStr)
    {
        return new StringBuilder(OriginalStr).Remove(index, length).Insert(index, SubsituteStr).ToString();
    }
}


4

আপনি যদি পারফরম্যান্সের বিষয়ে চিন্তা করেন তবে আপনি যে জিনিসটি এখানে এড়াতে চান তা হ'ল বরাদ্দ। এবং যদি আপনি। নেট কোর ২.১++ এ আছেন (অথবা এটি এখনও অপ্রকাশিত, নেট স্ট্যান্ডার্ড ২.১), তবে আপনি এই string.Createপদ্ধতিটি ব্যবহার করে করতে পারেন :

public static string ReplaceAt(this string str, int index, int length, string replace)
{
    return string.Create(str.Length - length + replace.Length, (str, index, length, replace),
        (span, state) =>
        {
            state.str.AsSpan().Slice(0, state.index).CopyTo(span);
            state.replace.AsSpan().CopyTo(span.Slice(state.index));
            state.str.AsSpan().Slice(state.index + state.length).CopyTo(span.Slice(state.index + state.replace.Length));
        });
}

এই পদ্ধতির বিকল্পগুলির চেয়ে বোঝা শক্ত, তবে এটি কেবলমাত্র একমাত্র যা কল প্রতি একমাত্র অবজেক্ট বরাদ্দ করবে: সদ্য নির্মিত স্ট্রিং।


3

আপনি কিছু লিঙ্ক চেষ্টা করতে পারেন:

string str = "ABCDEFGHIJ";
str = str.Substring(0, 2) + "ZX" + str.Substring(5);

3

অন্যান্যদের মতো Substring()ফাংশনটিও এখানে রয়েছে বলে উল্লেখ করেছেন :

static void Main(string[] args)
{
    string input = "ABCDEFGHIJ";

    string output = input.Overwrite(3, "ZX"); // 4th position has index 3
    // ABCZXFGHIJ
}

public static string Overwrite(this string text, int position, string new_text)
{
    return text.Substring(0, position) + new_text + text.Substring(position + new_text.Length);
}

এছাড়াও আমি StringBuilderসমাধানটির বিপরীতে এটি টাইম করেছিলাম এবং ৯০০ টি কৌশল বনাম ৮ 8৫ টি পেয়েছি So সুতরাং এটি কিছুটা ধীর।


@ হারুন.এস - না এটি করে না। আমার উদাহরণ "ABCDEFGHIJ"এবং "ZX"বিভিন্ন দৈর্ঘ্যের হয়।
জন আলেক্সিউ


2

এই পোস্টের সাহায্যে, আমি অতিরিক্ত দৈর্ঘ্যের চেক সহ নিম্নলিখিত ফাংশন তৈরি করি

public string ReplaceStringByIndex(string original, string replaceWith, int replaceIndex)
{
    if (original.Length >= (replaceIndex + replaceWith.Length))
    {
        StringBuilder rev = new StringBuilder(original);
        rev.Remove(replaceIndex, replaceWith.Length);
        rev.Insert(replaceIndex, replaceWith);
        return rev.ToString();
    }
    else
    {
        throw new Exception("Wrong lengths for the operation");
    }
}

2

স্ট্রিংটিতে ইউনিকোড চর থাকলে (ইমোজিসের মতো) অন্য সমস্ত উত্তরগুলি কাজ করে না কারণ একটি ইউনিকোড চরটি চরের চেয়ে বেশি বাইট।

উদাহরণ : ইমোজি '🎶' বাইটে রূপান্তরিত হবে, 2 টি অক্ষরের সমান হবে weight সুতরাং, যদি আপনার স্ট্রিংয়ের শুরুতে ইউনিকোড চর স্থাপন করা হয় তবে offsetপ্যারামিটার স্থানান্তরিত হবে)।

এই বিষয়টির সাথে আমি স্ট্রিংইনফো ক্লাসটি এড়াতে নিক মিলারের অ্যালগরিদমকে রেখে অবস্থান প্রতিস্থাপনের জন্য প্রসারিত করি:

public static class StringInfoUtils
{
    public static string ReplaceByPosition(this string str, string replaceBy, int offset, int count)
    {
        return new StringInfo(str).ReplaceByPosition(replaceBy, offset, count).String;
    }

    public static StringInfo ReplaceByPosition(this StringInfo str, string replaceBy, int offset, int count)
    {
        return str.RemoveByTextElements(offset, count).InsertByTextElements(offset, replaceBy);
    }

    public static StringInfo RemoveByTextElements(this StringInfo str, int offset, int count)
    {
        return new StringInfo(string.Concat(
            str.SubstringByTextElements(0, offset),
            offset + count < str.LengthInTextElements
                ? str.SubstringByTextElements(offset + count, str.LengthInTextElements - count - offset)
                : ""
            ));
    }
    public static StringInfo InsertByTextElements(this StringInfo str, int offset, string insertStr)
    {
        if (string.IsNullOrEmpty(str?.String))
            return new StringInfo(insertStr);
        return new StringInfo(string.Concat(
            str.SubstringByTextElements(0, offset),
            insertStr,
            str.LengthInTextElements - offset > 0 ? str.SubstringByTextElements(offset, str.LengthInTextElements - offset) : ""
        ));
    }
}

dotnetfiddle.net/l0dqS5 আমি ইউনিকোডে ব্যর্থ হওয়ার জন্য অন্যান্য পদ্ধতিগুলি পেতে পারি না। আপনার ব্যবহারের কেসটি প্রদর্শন করতে দয়া করে ফিজলটিকে পরিবর্তন করুন। ফলাফল খুব আগ্রহী।
মার্কাস

1
@ মারকাসহুজ আপনার স্ট্রিংয়ের শুরুতে ইউনিকোড চরগুলি রাখার চেষ্টা করুন যেমন: ডটনেটফিডেল . net / 3 ভি 2 কে 3 ওয়াই । আপনি কেবলমাত্র শেষ লাইনটি ভালভাবে দেখবেন এবং চতুর্থ স্থানটি 4 র্থ স্থানে স্থাপন করবেন (অন্য ক্ষেত্রে, ইউনিকোড
চরটি

আপনি ঠিক বলেছেন, এটি পরিষ্কার নয়। অন্যরা কেন উত্তর দেয় না সে সম্পর্কে আরও ব্যাখ্যা যুক্ত করতে আমি আমার উত্তর আপডেট করেছি
জিজিও

1

আমি নিম্নলিখিত প্রয়োজনীয়তা সহ একটি সমাধান খুঁজছিলাম:

  1. শুধুমাত্র একটি একক, এক-লাইন এক্সপ্রেশন ব্যবহার করুন
  2. কেবল সিস্টেম অন্তর্নির্মিত পদ্ধতি ব্যবহার করুন (কোনও কাস্টম বাস্তবায়িত ইউটিলিটি নেই)

সমাধান ঘ

যে সমাধানটি আমার পক্ষে সবচেয়ে উপযুক্ত হয় তা হ'ল:

// replace `oldString[i]` with `c`
string newString = new StringBuilder(oldString).Replace(oldString[i], c, i, 1).ToString();

এটি ব্যবহার করে StringBuilder.Replace(oldChar, newChar, position, count)

সমাধান 2

অন্য সমাধানগুলি যা আমার প্রয়োজনীয়তা পূরণ করে তা হ'ল Substringকনটাক্টেশন সহ ব্যবহার করা:

string newString = oldStr.Substring(0, i) + c + oldString.Substring(i+1, oldString.Length);

এটিও ঠিক আছে। আমি অনুমান করি যে এটি প্রথম এক পারফরম্যান্স অনুযায়ী দক্ষ নয় (অপ্রয়োজনীয় স্ট্রিং কংক্রিটেশনের কারণে)। তবে অকালীন অপটিমাইজেশন হ'ল সমস্ত অশুভের মূল

আপনি যেটি সবচেয়ে পছন্দ করেন তা চয়ন করুন :)


সমাধান 2 কাজ করে তবে সংশোধন প্রয়োজন: স্ট্রিং নিউ স্ট্রিং = ওল্ড স্ট্রেসারসবস্ট্রিং (0, i) + সি + ওল্ডস্ট্রিং.সুবস্ট্রিং (আই + 1, ওল্ড স্ট্রিং।লেন্থ- (আই + 1));
ইউরা জি

0

এটি ব্যবহার করা ভাল String.substr()

এটার মত:

ReplString = GivenStr.substr(0, PostostarRelStr)
           + GivenStr(PostostarRelStr, ReplString.lenght());

0
string myString = "ABCDEFGHIJ";
string modifiedString = new StringBuilder(myString){[3]='Z', [4]='X'}.ToString();

আমাকে আমার সমাধানটি ব্যাখ্যা করতে দিন।
দুটি অক্ষর 'জেড' এবং 'এক্স' দিয়ে তার দুটি নির্দিষ্ট পজিশনে ("পজিশন 4 থেকে পজিশন 5") স্ট্রিং পরিবর্তন করার সমস্যার বিবৃতি দেওয়া হয়েছে এবং স্ট্রিং বদলে স্ট্রিং বদলানোর জন্য পজিশন সূচকটি ব্যবহার করতে জিজ্ঞাসা করুন ) পদ্ধতি (প্রকৃত স্ট্রিংয়ে কিছু চরিত্রের পুনরাবৃত্তি হওয়ার সম্ভাবনার কারণেই হতে পারে), আমি Substring()স্ট্রিং Concat()বা স্ট্রিং Remove()এবং Insert()পদ্ধতির ব্যবহারের চেয়ে লক্ষ্য অর্জনের জন্য ন্যূনতমবাদী পদ্ধতির ব্যবহার করতে পছন্দ করব । যদিও এই সমস্ত সমাধানগুলি একই লক্ষ্য অর্জনে উদ্দেশ্যটিকে পরিবেশন করবে, তবে এটি কেবলমাত্র ব্যক্তিগত পছন্দ এবং ন্যূনতম পদ্ধতির সাথে নিষ্পত্তির দর্শনের উপর নির্ভর করে।
আমার সমাধানটি ফিরে আসার জন্য উপরে উল্লেখ করা হয়েছে, যদি আমরা আরও ঘনিষ্ঠভাবে নজর রাখিstring এবং এরStringBuilder, উভয়ই অভ্যন্তরীণভাবে একটি প্রদত্ত স্ট্রিংকে অক্ষরের অ্যারে হিসাবে বিবেচনা করে। যদি আমরা এর বাস্তবায়নের দিকে লক্ষ্যStringBuilderএটি internal char[] m_ChunkChars;প্রদত্ত স্ট্রিং ক্যাপচার করার জন্য " " এর মতো অভ্যন্তরীণ কিছু পরিবর্তনশীল কিছু বজায় রাখে । এখন এটি যেহেতু অভ্যন্তরীণ পরিবর্তনশীল, তাই আমরা সরাসরি এটির অ্যাক্সেস করতে পারি না। বাহ্যিক বিশ্বের জন্য, অক্ষর অ্যারে অ্যাক্সেস করতে এবং পরিবর্তন করতে সক্ষম হতে, সূচক StringBuilderসম্পত্তিগুলির মাধ্যমে তাদের প্রকাশ করে যা নীচের মতো দেখতে কিছু দেখায়

    [IndexerName("Chars")]
    public char this[int index]
    {
      get
      {
        StringBuilder stringBuilder = this;
        do
        {
          // … some code
            return stringBuilder.m_ChunkChars[index1];
          // … some more code
        }
      }
      set
      {
        StringBuilder stringBuilder = this;
        do
        {
            //… some code
            stringBuilder.m_ChunkChars[index1] = value;
            return;
            // …. Some more code
        }
      }
    }

আমার সমাধান উপরে উল্লিখিত এই সূচকটির অভ্যন্তরীণ রক্ষণাবেক্ষণের অক্ষর অ্যারে যা আইএমও দক্ষ এবং নূন্যতমবাদী সরাসরি পরিবর্তন করতে সক্ষম করার ক্ষমতা অর্জন করে verage

BTW; আমরা উপরের সমাধানটি আরও বিস্তৃতভাবে নীচের মতো কিছু আবার লিখতে পারি

 string myString = "ABCDEFGHIJ";
 StringBuilder tempString = new StringBuilder(myString);
 tempString[3] = 'Z';
 tempString[4] = 'X';
 string modifiedString = tempString.ToString();

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

[IndexerName("Chars")]
public extern char this[int index] { [SecuritySafeCritical, __DynamicallyInvokable, MethodImpl(MethodImplOptions.InternalCall)] get; }

এবং সর্বশেষে তবে কমপক্ষে এই সমাধানটি এই নির্দিষ্ট সমস্যার ক্ষেত্রে কেবলমাত্র উপযুক্ত উপযুক্ত যেখানে জিজ্ঞাসাটি কেবলমাত্র কয়েকটি অবস্থানের একটি পরিচিত অবস্থান সূচক সম্মুখের সাথে প্রতিস্থাপন করবে। এটির জন্য উপযুক্ত উপযুক্ত হতে পারে না যখন প্রয়োজনীয়তাটি একটি দীর্ঘ দৈর্ঘ্যের স্ট্রিংকে পরিবর্তন করতে হয় অর্থাৎ অক্ষরগুলির সংখ্যা পরিবর্তনের জন্য সংখ্যায় বড় হয়।


1
এই কোডটি প্রশ্নের উত্তরটি কীভাবে দেয় তার ব্যাখ্যা করতে দয়া করে আপনার উত্তরটি সম্পাদনা করুন
shshkus

0
String timestamp = "2019-09-18 21.42.05.000705";
String sub1 = timestamp.substring(0, 19).replace('.', ':'); 
String sub2 = timestamp.substring(19, timestamp.length());
System.out.println("Original String "+ timestamp);      
System.out.println("Replaced Value "+ sub1+sub2);

0

এখানে একটি সাধারণ এক্সটেনশন পদ্ধতি:

    public static class StringBuilderExtensions
    {
        public static StringBuilder Replace(this StringBuilder sb, int position, string newString)
            => sb.Replace(position, newString.Length, newString);

        public static StringBuilder Replace(this StringBuilder sb, int position, int length, string newString)
            => (newString.Length <= length)
                ? sb.Remove(position, newString.Length).Insert(position, newString)
                : sb.Remove(position, length).Insert(position, newString.Substring(0, length));
    }

এটি এর মতো ব্যবহার করুন:

var theString = new string(' ', 10);
var sb = new StringBuilder(theString);
sb.Replace(5, "foo");
return sb.ToString();

-2

আমি বিশ্বাস করি সবচেয়ে সহজ উপায়টি এটি হবে: (স্ট্রিংবিল্ডার ছাড়াই)

string myString = "ABCDEFGHIJ";
char[] replacementChars = {'Z', 'X'};
byte j = 0;

for (byte i = 3; i <= 4; i++, j++)  
{                   
myString = myString.Replace(myString[i], replacementChars[j]);  
}

এটি কাজ করে কারণ ধরণের স্ট্রিংয়ের একটি ভেরিয়েবলকে চর ভেরিয়েবলের অ্যারে হিসাবে বিবেচনা করা যেতে পারে। আপনি উদাহরণস্বরূপ স্ট্রিং ভেরিয়েবলের দ্বিতীয় অক্ষরটিকে "মাইস্ট্রিং" নামটি মাইস্ট্রিং হিসাবে উল্লেখ করতে পারেন [1]


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