5

約1MBのサイズの文字列があります。要件は、サイズ 1 MB の別の一時文字列を割り当てずに、文字列を逆にすることです。次のコードを試しました

string name = "abcde";

string target = "";
for(int i = name.Length - 1; i >=0; i--)
{
    target += name[i];
    name = name.Remove(i);                
    int n = name.Length;
}

しかし、私の友人は、関数を使用するname.Remove(i)と新しい文字列が返されると言っていますが、古い文字列がメモリから削除されることは保証されていないため、サイズが縮小されるという保証はありません。それは本当ですか?もしそうなら、余分なメモリを割り当てずに文字列を逆にするために利用できる他のオプションはありますか?

4

14 に答える 14

13

Your string "abcde" is a constant in memory. You can't change it, as it is immutable. What you want is to create a new string, and for this you need new memory.

于 2012-07-05T08:56:55.453 に答える
6

使用StringBuilderすると、char配列で操作できますが、string不変であるため、では操作できません

于 2012-07-05T09:00:45.830 に答える
3

文字列は不変であり、新しいメモリを割り当てずに元に戻すことはできません

MSDN の文字列

文字列は不変です。オブジェクトの作成後に文字列オブジェクトの内容を変更することはできませんが、構文上は変更できるかのように見えます。

同じリンクから、次の例を参照してください。

string b = "h";
b += "ello";

そして説明。

このコードを記述すると、コンパイラは実際に新しい文字列オブジェクトを作成して新しい文字列を保持し、その新しいオブジェクトが b に割り当てられます。文字列 "h" はガベージ コレクションの対象になります。

于 2012-07-05T08:57:25.470 に答える
2

文字列は不変です。宣言すると変更できません。したがって、何をしようとしても、新しいメモリが作成されて使用されます。

string name = "aaaaa":
name = name.Remove(0); // this is allocating new memory.
于 2012-07-05T08:57:39.910 に答える
1

StringBuilder は Mutable であり、この場合、可能な限り最高の効率を提供するはずです

string inpuStr = "The quick brown fox jumped over the lazy dog...blah blah blah up to 1MB";
StringBuilder builder = new StringBuilder();
            for (int i = inpuStr.Length - 1; i >= 0; i--)
            {
                builder.Append(inpuStr[i]); 
            }
           return builder.ToString();
于 2014-05-12T05:56:25.703 に答える
1

元のデータをある程度制御できる場合は、これを実行できるはずです。char[]たとえば、を作成せずにを要求できる場合はstring、その場で元に戻すことができます。

たとえば、あなたのvar name = new char[] { 'a', 'b', 'c', 'd', 'e'}例では、代わりに文字列を使用して、それを元に戻すことができます。

(明らかに、1MB の文字列に対してこれを行うことはできませんが、最初に文字列を代わりにロードできれば、どこからでも文字列を取得できますchar[]...)

しか持てない場合はstring、運が悪いです。それらは不変です。何らかの方法でコピーすることによってのみ、文字列を変更できます。

于 2012-07-05T08:59:12.410 に答える
0

編集:プロットが完全に失われました。最近 C++ を使いすぎているため、C# の文字列が不変であることを忘れていました。

つまり、C# で文字列を変更するには、新しいメモリを割り当てる必要があります。次のようなことを行うことで、最も簡単な方法でこれを行うことができます。

string ReverseString(string value)
{
    if (!string.IsNullOrEmpty(value))
    {
        char[] newBuffer = new char[value.Length];
        for(int i = 0; i < value.Length; i++)
            newBuffer[newBuffer.Length - i - 1] = value[i];
        value = new string(newBuffer);
    }
    return value;
}
于 2012-07-05T08:54:51.360 に答える
0
you can try with linq to reverse

    string original = "abcde";
    string reverseValue = new string(original.Reverse().ToArray());

you can try also with 

string result= new string(original.Select((c, index) => new { c, index })
                                         .OrderByDescending(x => x.index)
                                         .ToArray());
于 2012-07-05T08:56:25.163 に答える
0

追加の割り当てを行わないことを真剣に考えている場合はfix、文字列にunsafeポインター コードを使用する必要があります。または、おそらく、char[]リフレクションを使用して内部への参照を取得します。

あなたは本当にこれをしたくありません。本当。つまり、本当に。学習演習以外でこれを行わないでください。本番環境でそのようなコードを見つけた場合、彼らは武器を持ってあなたを探しに来る可能性があります。

私はそのようなコードを書き込もうとはしません (間違えるとわかっているので)。しかし、ここにあなたが始めるためのいくつかのリンクがあります:

  • Strings Undocumented - かなり古い記事ですが、最良の例があります。
  • John Skeet on Strings - あなたが望むものには少し高いレベルですが、始めるには良い場所です.
于 2012-07-11T07:03:50.780 に答える
0

実際には、逆にしたい文字列が占有しているのと同じ量のメモリを割り当てずに、文字列を逆にする正しい方法はありません。(理論的には、メモリ内の文字列を逆にすることは可能ですが、これはお勧めできません。その領域に入るつもりはありません)。次に、文字列自体を逆にします。私は StringExtensions と呼ばれる小さなプロジェクトに取り組んでいます。このプロジェクトでは、文字列を操作するときに発生する可能性のある問題をすべて解決しようとしています。最大の問題の 1 つは、フレームワーク全体で広く使用されている UTF-16 エンコーディングを使用することです。文字列を逆にする私の実装は次のようになります。

    static IEnumerable<Tuple<int, int>> GetTextElementSegments(string value)
    {
        int[] elementOffsets = StringInfo.ParseCombiningCharacters(value);

        int lastOffset = -1;
        foreach (int offset in elementOffsets)
        {
            if (lastOffset != -1)
            {
                int elementLength = offset - lastOffset;
                Tuple<int, int> segment = new Tuple<int,int>(lastOffset, elementLength);
                yield return segment;
            }

            lastOffset = offset;
        }

        if (lastOffset != -1)
        {
            int lastSegmentLength = value.Length - lastOffset;

            Tuple<int, int> segment = new Tuple<int, int>(lastOffset, lastSegmentLength);
            yield return segment;
        }
    }

    static void Main(string[] args)
    {
        string input = "t\u0301e\u0302s\u0303t\u0304";
        StringBuilder resultBuilder = new StringBuilder(input.Length);

        var segments = GetTextElementSegments(input);

        foreach (var segment in segments.Reverse())
        {
            resultBuilder.Append(input, segment.Item1, segment.Item2);
        }

        Debug.Assert(resultBuilder.ToString() == "t\u0304s\u0303e\u0302t\u0301s");
    }

これは、サロゲート ペア、Unicode マーク コードポイントを処理し、入力文字列自体が占める量と同様のメモリのみを割り当てることに注意してください。

于 2012-07-05T09:31:30.597 に答える
-1

This should help

string reverse = new string("ABCDEFGHI".ToCharArray().Reverse().ToArray());
于 2012-07-05T08:56:39.290 に答える