程序功能为:给定一个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++编译器的优化问题,不同平台上面的编译器可能有所不同。
结束!