c++ demo: 单词转换

来源:互联网 发布:淘宝一元包邮的店 编辑:程序博客网 时间:2024/05/21 10:02

程序功能为:给定一个string,将它转换成为另一个string。程序的输入是两个文件,第一个文件保存一些规则,用来转换第二个文件的文本。每条规则由两部分组成:一个可能出现在输入文本中的单词和一个用来替换它的短语。表达的含义是,每当第一个单词出现在输入中时,就将它替换为对应的短语。第二个输入文件包含要转换的文本。
本人刚刚开始学习C++,从简单的程序入手,循序渐进。本程序来自primer c++中的。
比如:
第一个文件的内容:

u youa are

第二个文件的内容:

u a welcome!

程序输出为:

you are welcome!

源码:

Transformer.h 文件,定义了三个方法,其中word_transform方法将调用另外两个方法。

#include <iostream>#include <sstream>#include <c++/map>#include <c++/fstream>#ifndef TEXTTEST_TRANSFORMER_H#define TEXTTEST_TRANSFORMER_Husing namespace std;class Transformer {public:    //转换的总体逻辑函数    void word_transform(ifstream &map_file, ifstream &input);    //把转换规则文件中的内容保存到一个哈希表中,key为被转换的内容,value是转换的内容。作用:快速查找,查找的时间复杂度为0(1)    map<string, string> buildMap(ifstream &map_file);    //转换单词:如果在转换规则文件中存在该单词,就转换,如果没有,就返回原值。    const string& transform(const string &s, const map<string, string> &m);};#endif //TEXTTEST_TRANSFORMER_H

Transformer.cpp文件:实现头文件Transformer.h

//// Created by liangyh on 7/8/2017.//#include "Transformer.h"map<string, string> Transformer::buildMap(ifstream &map_file){    map<string, string> trans_map;    string key;    string value;    while(map_file >> key && getline(map_file, value)){        if(value.size() > 1){            //使用substr的原因是去掉字符串前面的空格            trans_map[key] = value.substr(1);        }else{            throw runtime_error("no rule for " + key);        }    }    return trans_map;};void Transformer::word_transform(ifstream &map_file, ifstream &input){    auto trans_map = buildMap(map_file);    string text;    while(getline(input, text)){        istringstream stream(text);        string word;        bool firstWord = true;        while(stream >> word){            if(firstWord){                firstWord = false;            }else{                cout << " ";            }            cout << transform(word, trans_map);        }        cout << endl;    }}//形参s使用了引用地址,避免在函数返回的时候进行不必要的复制。const string& Transformer::transform(const string &s, const map<string, string> &m){    auto map_it = m.find(s);    if(map_it != m.cend()){        return map_it -> second;    }else{        return s;    }}

主函数:

#include <iostream>#include <c++/fstream>#include <c++/memory>#include "Transformer.h"using namespace std;int main0(int argc, char* argv[]) {    string fileName1 = "C:\\Users\\liangyh\\Desktop\\TEMP\\t1.txt";    string fileName2 = "C:\\Users\\liangyh\\Desktop\\TEMP\\t2.txt";    ifstream inFile(fileName1.c_str());    ifstream inFile2(fileName2.c_str());    if(inFile.is_open() && inFile2.is_open()){        shared_ptr<Transformer> transformer(new Transformer());//智能指针        transformer->word_transform(inFile, inFile2);    }    return 0;}

思考和改进

1、在main函数中可以不使用智能指针的,程序将变成下面样子:

//        shared_ptr<Transformer> transformer(new Transformer());//        transformer->word_transform(inFile, inFile2);        Transformer transformer;        transformer.word_transform(inFile, inFile2);

使用智能指针的时候,Transformer对象保存在堆中,程序自动管理内存的回收工作。修改之后,对象将保存在栈中,main函数退出之后,内存自动释放。

2、c++中的函数形参是值传递,上面的程序使用了&的引用参数,也就是引用传参方式,避免了不必要的数据复制。这一点和Java有很大的区别。

3、上面的buildMap函数中的返回值是

map<string, string> trans_map;

注意,trans_map是一个局部变量,函数结束之后,这个局部变量应该会被回收,buildMap函数的调用者应该不会得到返回值的,可是,现实并不是这样子的:调用buildMap函数可以得到它的返回值。为什么呢?下面我们进行一个实验:
代码如下面所示:在方法中申明局部变量,并将其作为函数的返回值,同时打印函数内部该变量的地址和返回值的地址。

#include <iostream>#include <c++/fstream>#include <c++/memory>#include "Transformer.h"#include <c++/map>using namespace std;map<string, string> returnTest_map(){    map<string,string> result;    result["1"] = "11";    result["2"] = "22";    cout << "map: " << &result << endl;    return result;};int returnTest_int(){    int result = 2;    cout <<"int: "<< &result << endl;    return result;}long returnTest_long(){    long result = 3L;    cout <<"long: "<< &result << endl;    return result;}string returnTest_string(){    string result("hello");    cout <<"string: "<< &result << endl;    return result;}//错误:返回局部变量的引用,函数结束之后,变量就被回收了。/*int& referenceTest(){    int result = 2 + 3;    return result;}*/int main(int argc, char* argv[]) {    map<string, string> result = returnTest_map();    cout <<"map: "<< &result << endl;    int result2 = returnTest_int();    cout << "int: " << &result2 << endl;    string result3 = returnTest_string();    cout << "string: " << &result3 << endl;//    int result4 = referenceTest();//    cout << result4 << endl;    long result5 = returnTest_long();    cout << "long: " << &result5 << endl;    return 0;}

结果:

map: 0x24fe10map: 0x24fe10int: 0x24fd9cint: 0x24fe0cstring: 0x24fde0string: 0x24fde0long: 0x24fd9clong: 0x24fddc

结果表明,map、string的变量前后是同一个变量,而int和long是不同的变量。这样的结果说明什么呢?1、对于int和long,函数在返回值的时候进行了拷贝操作。2、对于string和map,函数在返回值的时候没有进行内容的拷贝,这些内容不是保存在“栈”中,而是在“堆”中或者其他结构中。3、这个很可能涉及到c++编译器的优化问题,不同平台上面的编译器可能有所不同。

结束!

原创粉丝点击