Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#/.NET中的可变字符串编辑_C#_.net - Fatal编程技术网

C#/.NET中的可变字符串编辑

C#/.NET中的可变字符串编辑,c#,.net,C#,.net,我想在.NET应用程序中就地获取和编辑字符串。我知道,StringBuilder允许我进行就地追加、插入和替换,但它不允许以一种简单的方式进行以下操作: while (script.IndexOf("@Unique", StringComparison.InvariantCultureIgnoreCase) != -1) { int Location = script.IndexOf("@Unique", StringComparison.InvariantCultureIgnoreCas

我想在.NET应用程序中就地获取和编辑字符串。我知道,
StringBuilder
允许我进行就地追加、插入和替换,但它不允许以一种简单的方式进行以下操作:

while (script.IndexOf("@Unique", StringComparison.InvariantCultureIgnoreCase) != -1)
{
   int Location = script.IndexOf("@Unique", StringComparison.InvariantCultureIgnoreCase);
   script = script.Remove(Location, 7);
   script = script.Insert(Location, Guid.NewGuid().ToString());
}
因为
StringBuilder
中没有
IndexOf
。是否有人有一种有效的方法来对文本信息进行就地编辑

编辑#1:
更改了示例,使每个“替换”都需要不同的结果更加明显。

StringBuilder的制作使您可以轻松添加到其中,但折衷是很难在其中搜索,尤其是索引它更困难(即速度较慢)。 如果需要“就地”修改某些字符,最好在生成的字符串上进行修改


但是很难从你的问题中知道什么是适合你的正确答案,我的感觉是你不需要在StringBuilder中进行就地更换,问题出在其他地方/你做错了什么。

如果你的代码真的这么简单,那么为什么不使用一个内置的
Replace
方法

编辑以下评论…

您可以使用以下参数将每个引用替换为单独的值:

string foo = "blah blah @Unique blah @Unique blah blah @Unique blah";

// replace each occurrence of "@Unique" with a separate guid
string bar = Regex.Replace(foo, "@Unique",
    new MatchEvaluator(m => Guid.NewGuid().ToString()),
    RegexOptions.IgnoreCase));

如何使用StringBuilder方法:


你要更换多少人

如果不是四位数,那么只接受新的字符串实例,您可能过早地优化了


另一个解决方案。。。在“@uniqueID”上拆分,然后重新加入StringBuilder,为每次迭代添加分隔符。

您能使用字符串拆分有效地完成此操作吗

比如:

var sections = "a-@Unique-b-@Unique-c".Split(new string[] { "@Unique" }, StringSplitOptions.None);
int i;
StringBuilder builder = new StringBuilder();
for(i = 0; i < sections.Length - 1; i++)
{
    builder.Append(sections[i]);
    builder.Append(Guid.NewGuid().ToString());
}
builder.Append(sections[i]);

Console.WriteLine(builder.ToString());
Console.ReadKey(true);
var sections=“a-@Unique-b-@Unique-c”.Split(新字符串[]{“@Unique”},StringSplitOptions.None);
int i;
StringBuilder=新的StringBuilder();
对于(i=0;i
您需要使用非托管代码块 简单到声明一个指向字符串的指针并在内存中操作它

范例

unsafe
{
  char* ip;
  ip = &to_your_string;
}

用户Dennis提供了一个。有了它,您应该能够以这种方式使用StringBuilder。

很复杂,但应该是一个性能良好的解决方案

    public StringBuilder Replace(this StringBuilder sb, string toReplace, Func<string> getReplacement)
    {
        for (int i = 0; i < sb.Length; i++)
        {
            bool replacementFound = true;
            for (int toReplaceIndex = 0; toReplaceIndex < toReplace.Length; toReplaceIndex++)
            {
                int sbIndex = toReplaceIndex + i;
                if (sbIndex < sb.Length)
                {
                    return sb;
                }
                if (sb[sbIndex] != toReplace[toReplaceIndex])
                {
                    replacementFound = false;
                    break;
                }
            }
            if (replacementFound)
            {
                string replacement = getReplacement();
                // reuse the space of the toReplace string
                for (int replacementIndex = 0; replacementIndex < toReplace.Length && replacementIndex < replacement.Length; replacementIndex++)
                {
                    int sbIndex = replacementIndex + i;
                    sb[sbIndex] = replacement[i];
                }
                // remove toReplace string remainders
                if (replacement.Length < toReplace.Length)
                {
                    sb.Remove(i + replacement.Length, replacement.Length - toReplace.Length)
                }
                // insert chars not yet inserted
                if (replacement.Length > toReplace.Length)
                {
                    sb.Insert(i + toReplace.Length, replacement.ToCharArray(toReplace.Length, toReplace.Length - replacement.Length));
                }
            }
        }
        return sb;
    }

我的问题是,在上面的示例中,@Unique的每个实例都需要不同的值,因此我无法在字符串中进行全局查找和替换。@JasonRShaver:这可以使用
Regex.replace
完成。看看我的编辑。@Luke:这个解决方案看起来不错,但它是否支持StringBuilder,就像在需求中一样。我猜“JasonRShaver”可以用问题中的字符串完成。这是一个非常有趣的解决方案。我很好奇regex处理器在内存方面的表现如何。MatchEvaluator对我来说也是新的,我很高兴现在就“知道”了。稍后我将对此方法制作一个测试应用程序,看看它是否完全解决了问题。@JasonRShaver这些方法在内部使用
StringBuilder
(并执行一些子串接),因此应该相当有效。我刚刚意识到,necro comment:-DIf字符串有两个@Unique,那么两个替换将具有相同的值,而不是唯一的值。这就是为什么他不想使用IndexOf,所以每次替换都会生成一个新的唯一值。我认为StringBuilder不能在这种情况下使用。您只需将其作为字符串进行处理,可能您可以在将其添加到StringBuilder之前对其进行处理。系统将在我们预期的峰值处理大约300000项。@Jason-在峰值负载下,此方法的性能规格是什么?执行一个实现并在加载时对其进行基准测试。如果符合规格,请发货。如果没有,请分析它+1.看起来不安全不允许您声明指向字符串的指针。对不起的:(1)这是几个月以来我见过的最可怕的C代码,我甚至不会考虑做这样的事情。我很高兴.NET设计者保证它不会起作用。@ TruteWr:不幸的是,很容易对现有字符串进行突变。<代码>字符串类有私有<代码> AppDeNePix< /Calp>,<代码>可以使用反射来调用这些方法。但是我同意你的观点,甚至在任何真实世界代码中考虑使用这些方法都是疯狂的。对不起,TrueWill我并不是想让你哭……但是不安全是.NETFramework的一部分,而.NET设计者是设计它的。这是一个不同的故事。
    public StringBuilder Replace(this StringBuilder sb, string toReplace, Func<string> getReplacement)
    {
        for (int i = 0; i < sb.Length; i++)
        {
            bool replacementFound = true;
            for (int toReplaceIndex = 0; toReplaceIndex < toReplace.Length; toReplaceIndex++)
            {
                int sbIndex = toReplaceIndex + i;
                if (sbIndex < sb.Length)
                {
                    return sb;
                }
                if (sb[sbIndex] != toReplace[toReplaceIndex])
                {
                    replacementFound = false;
                    break;
                }
            }
            if (replacementFound)
            {
                string replacement = getReplacement();
                // reuse the space of the toReplace string
                for (int replacementIndex = 0; replacementIndex < toReplace.Length && replacementIndex < replacement.Length; replacementIndex++)
                {
                    int sbIndex = replacementIndex + i;
                    sb[sbIndex] = replacement[i];
                }
                // remove toReplace string remainders
                if (replacement.Length < toReplace.Length)
                {
                    sb.Remove(i + replacement.Length, replacement.Length - toReplace.Length)
                }
                // insert chars not yet inserted
                if (replacement.Length > toReplace.Length)
                {
                    sb.Insert(i + toReplace.Length, replacement.ToCharArray(toReplace.Length, toReplace.Length - replacement.Length));
                }
            }
        }
        return sb;
    }
var sb = new StringBuilder(script);

script = sb.Replace("@Unique", () => Guid.NewGuid().ToString()).ToString();