到目前为止,我只编写了控制台应用程序。我的第一个使用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英雄(如上所述,我通常只构建控制台应用程序),所以这可能是一个新手的错误。我做错了什么?
答案 0 :(得分:3)
在C ++ / CLI中,System::String
是不可变的,因此Remove
会创建一个新的String^
。这意味着您需要分配结果:
phrase = phrase->Remove( CoordsStart , CoordsEnd-CoordsStart );
您的使用情况也是如此:
TempString = DestroyCoords(TempString);
BoxOutput->Text = TempString;
请注意,这仍然无效,因为您需要反向遍历字符串(因为第一次删除后索引会出错)。
答案 1 :(得分:2)
这里没有MFC,这是Microsoft用于在C ++中编写.NET程序的C ++ / CLI。
.NET System::String
类是不可变的,因此您希望修改字符串的任何操作实际上都会返回一个带有调整的新字符串。
另一个问题是你在迭代它时试图修改一个容器(字符串)。不要使用Remove
,而是使用StringBuilder
变量并复制要保留的字符串部分。这意味着只有一个副本,并且比重复调用Remove
的速度快得多,每个调用都会复制一次。它不会干扰迭代。
这是正确的方法:
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();