您的位置:首页 > 编程语言 > C语言/C++

SSD6中Exercise4 (substitute.cpp) 答案解析

2008-12-01 22:55 162 查看
今天终于把Exercise4搞定了,昨天大约优化了0.38秒,今天优化了0.52秒,跨越了一大步。

在我们未加任何修饰执行此代码时,其执行后所用时间如图(摘抄主要):

FunctionCallee Exclusive Time
main1.495306
IndexOf( String, int32 )

0.771013
insertChar( String, int32, String, int32 )0.444054
我们发现insertChar()函数里面就一条return语句,这完全没必要,何必还调用一个函数呢,申请栈释放栈很浪费时间,然后我们去掉这个函数,直接在别的函数里面用它里面的语句。

我们再来看

for (int i = 0; i < replacement->Length; i++) {

data = insertChar(data, loc+i, replacement, i);

// data->Insert(loc + i, replacement->Substring(i, 1));

}

这个也没必要,何必一个一个的插入呢?整体插入就算了。因而可以改为

return data->Insert(loc,replacement);

对于indeof函数,占的时间实在太多,是该解决一下它,在原函数中间是这样的:

for (loc = data->IndexOf(pattern, 0); loc >= 0;

loc = data->IndexOf(pattern, 0)) {

// replace word

data = replace_word(data, loc, pattern->Length, replacement);

}

没必要总是从第一个找起吧!起先我想的是从上一次查找的结束的下一个位置开始查找,但这样有一个问题。例如我们用dd替换cd,有一个字符串为cccd,第一次替换后为ccdd,不应该只是往后找,因为此时前面也出现了cd,故而在这里我们可以从新得到的loc 前 pattern->length处开始查找,再往前开始找没意义。在这里还就是pattern->Length最好在外面用一个变量代替,如pl,放置循环次次都计算pattern->Length(你可能认为编译器足够聪明,但我们不敢保证它在这里“敢”优化,毕竟pattern是个指针,随时可以变,还是我们替他提早优化,参考《深入理解计算机系统》)。

故而这段程序改为:

int location = 0;

int pl = pattern->Length;

// find every occurrence of pattern:

for (loc = data->IndexOf(pattern, 0); loc >= 0;

loc = data->IndexOf(pattern, location)) {

// replace word

int dis = loc - pl;

if (dis >= 0)

{

location = dis;

}

else

{

location = 0;

}

data = replace_word(data, loc, pl, replacement);

改过的程序为:

#include <iostream>

using namespace std;

using namespace System;

using namespace System::IO;

using namespace System::Text;

//String* insertChar(String *data, int loc, String *replacement, int i) {

// return data->Insert(loc, replacement->Substring(i, 1));

//}

String* replace_word(String* data, int loc, int length, String* replacement) {

// delete the pattern string from loc:

data = data->Remove(loc, length);

// insert each character of the replacement string:

//for (int i = 0; i < replacement->Length; i++) {

// data = insertChar(data, loc+i, replacement, i);

// // data->Insert(loc + i, replacement->Substring(i, 1));

//}

return data->Insert(loc,replacement);

//->Insert(loc,replacement)

}

String* string_subst(String *data, String *pattern, String *replacement) {

try {

int loc;

int location = 0;

int pl = pattern->Length;

// find every occurrence of pattern:

for (loc = data->IndexOf(pattern, 0); loc >= 0;

loc = data->IndexOf(pattern, location)) {

// replace word

int dis = loc - pl;

if (dis >= 0)

{

location = dis;

}

else

{

location = 0;

}

data = replace_word(data, loc, pl, replacement);

}

return data;

} catch (Exception *e) {

Console::WriteLine("Error in substitute ");

Console::WriteLine(e->ToString());

return data;

}

}

String* batch_subst(String *data, const char* subs_filename) {

try {

String *subs_file = new String(subs_filename);

StreamReader *subs_reader = new StreamReader(subs_file);

String *pattern, *replacement, *separator;

while (subs_reader->Peek() >= 0) {

pattern = subs_reader->ReadLine();

replacement = subs_reader->ReadLine();

separator = subs_reader->ReadLine();

data = string_subst(data, pattern, replacement);

}

return data;

} catch(Exception* e ) {

Console::WriteLine( "Error in do_substitutions ");

Console::WriteLine( e->ToString());

return data;

}

}

void process_file(const char* filename, const char* subs_filename) {

StreamReader *reader;

StreamWriter *writer;

String *file = new String(filename);

try {

reader = new StreamReader( file );

String *data = reader->ReadToEnd();

data = batch_subst(data, subs_filename);

reader->Close();

// write the data

writer = new StreamWriter(file, false);

writer->Write(data);

writer->Close();

} catch(Exception* e) {

Console::WriteLine( "Error while processing file ");

Console::WriteLine( e->ToString());

}

}

int main(int argc, char *argv[]) {

if (argc < 3) {

cout << "Not enough input arguments" << endl;

cout << "Usage: substitute subs-file src1 src2 ..." << endl;

} else {

for (int i = 2; i < argc; i++) {

process_file(argv[i], argv[1]);

}

}

return 0;

}

我还准备优化那个reader->Close();writer->Close();没必要每次都关闭。但尝试了一下,最终失败。希望看过此文章的人不吝赐教,多多指导,共同学习。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: