c++ demo: 单词转换

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

u you
a are

第二个文件的内容:

u a welcome!

程序输出为:

you are welcome!

源码:

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

#include 
#include 
#include 
#include 

#ifndef TEXTTEST_TRANSFORMER_H
#define TEXTTEST_TRANSFORMER_H

using 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 
#include 
#include 
#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(new Transformer());//智能指针
        transformer->word_transform(inFile, inFile2);
    }

    return 0;
}

思考和改进

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

//        shared_ptr 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 
#include 
#include 
#include "Transformer.h"
#include 

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: 0x24fe10
map: 0x24fe10
int: 0x24fd9c
int: 0x24fe0c
string: 0x24fde0
string: 0x24fde0
long: 0x24fd9c
long: 0x24fddc

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

结束!

你可能感兴趣的:(c++)