1

到目前为止,我只编写了控制台应用程序。我的第一个使用 MFC 的应用程序(在 Visual Studio 2010 中)基本上是一个带有两个多行框的表单(使用带有 String^ 的 String[] 数组)和一个用于激活文本处理的按钮。它应该在 String^ 中搜索 [,查找其后面的 ] 并删除它们之间的所有字符(包括 [])。使用“普通”C++ 字符串,这并不难。然而,String^ 更像是一个对象,MSDN 告诉我要使用 Remove 方法。所以,我试图实现它。

public ref class Form1 : public System::Windows::Forms::Form
{
public:
    Form1(void)
    {
        InitializeComponent();
        //
        //TODO: Add the constructor code here
        //
    }
    String^ DestroyCoords(String^ phrase)
    {
        int CoordsStart = 0;
        int CoordsEnd = 0;
        int CharCount = 0;
        for each (Char ch in phrase)
        {
            if (ch == '[')
                CoordsStart = CharCount;
            if (ch == ']')
            {
                CoordsEnd = CharCount;
                //CoordsEnd = phrase->IndexOf(ch);
                phrase->Remove( CoordsStart , CoordsEnd-CoordsStart );
            }
            CharCount++;
        }
    return phrase;
    }

按钮使用方法:

private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
             TempString = String::Copy(BoxInput->Text);
             DestroyCoords(TempString);
             BoxOutput->Text = TempString;

该函数似乎在正确的时间到达了正确的位置,但短语->Remove() 方法完全没有做任何事情。我不是 OO 英雄(如前所述,我通常只构建控制台应用程序),所以它可能是一个菜鸟的错误。我究竟做错了什么?

4

2 回答 2

3

在 C++/CLI 中,System::String是不可变的,因此Remove创建了一个新的String^. 这意味着您需要分配结果:

phrase = phrase->Remove( CoordsStart , CoordsEnd-CoordsStart );

在您的使用中也是如此:

TempString = DestroyCoords(TempString);
BoxOutput->Text = TempString;

请注意,这仍然不起作用,因为您需要反向遍历您的字符串(因为第一次删除后索引将是错误的)。

于 2013-06-17T18:02:39.360 回答
2

No MFC here, that's the C++/CLI that Microsoft uses for writing .NET programs in C++.

The .NET System::String class is immutable, so any operations you expect to modify the string actually return a new string with the adjustment made.

A further problem is that you're trying to modify a container (the string) while iterating through it. Instead of using Remove, have a StringBuilder variable and copy across the parts of the string you want to keep. This means only a single copy and will be far faster than repeated calls to Remove each of which makes a copy. And it won't interfere with iteration.

Here's the right approach:

    int BracketDepth = 0;
    StringBuilder sb(phrase->Length); // using stack semantics
                                      // preallocated to size of input string
    for each (Char ch in phrase)
    {
        if (ch == '[') {              // now we're handling nested brackets
            ++BracketDepth;
        }
        else if (ch == ']') {         // and complaining if there are too many closing brackets
            if (!BracketDepth--) throw gcnew Exception();
        }
        else if (!BracketDepth) {     // keep what's not brackets or inside brackets
            sb.Append(ch);
        }
    }
    if (BracketDepth) throw gcnew Exception(); // not enough closing brackets
    return sb.ToString();
于 2013-06-17T18:03:01.930 回答