对C++ Primer的10.3.9单词转换的思考
这篇代码有几个知识点可以复习一下,而且小白学到了新知识o(╯□╰)o
1 #include <iostream> 2 #include <string> 3 #include <map> 4 #include <fstream> 5 #include <sstream> 6 using namespace std; 7 8 ifstream& open_file(ifstream&,const string&); 9 /*two input main parameter of main: 10 *The first is name of the word transformation file 11 *The second is name of the input to transform 12 */ 13 int main(int argc, char **argv ) 14 { 15 /*Use to hold the pair of word and trans_word: 16 Key is the word to look for in the input, Value is the word to use in the output 17 */ 18 map<string, string> trans_map; 19 string key, value; 20 if(argc != 3) 21 throw runtime_error("Wrong number of arguments!"); 22 ifstream map_file; 23 if (!open_file(map_file, argv[1])) 24 { 25 throw runtime_error("No transformation file!"); 26 } 27 //read the transformation map and build the map 28 while (map_file >>key >>value) 29 trans_map.insert(make_pair(key, value)); 30 31 ifstream input; 32 if(!open_file(input, argv[2])) 33 throw runtime_error("No input file!"); 34 string line; //hold each line from the input 35 36 //read the text to transform it a line at a time 37 while ( getline(input, line)) //read a line from the input to line 38 { 39 istringstream stream(line); 40 string word; 41 bool firstword = true; 42 while (stream >>word) 43 { 44 /*Use word find the key of trans_map*/ 45 map<string, string>::const_iterator map_it = trans_map.find(word); 46 if (map_it !=trans_map.end()) 47 /*if there is substitute for word, change the word*/ 48 word = map_it->second; 49 if (firstword) 50 firstword = false; 51 else 52 cout << " "; 53 cout << word; 54 } 55 cout << endl; 56 } 57 return 0; 58 } 59 60 ifstream& open_file(ifstream &in, const string &file ) 61 { 62 in.close(); 63 in.clear(); 64 in.open ( file.c_str() );//open the file we were given 65 return in; 66 }
首先理清楚单词转换的流程:
1.明确输入文件有两个:
①mapfile,单词转换集合,其第一个值为待转换单词,第二个值为转换后单词
②infile,输入文件
2.明确对文件的操作
①对于mapfile,如果打开正确的话,读入单词转换对,将其转化为:第一个值为key,第二个值为value;调用insert在容器中插入新元素,循环执行。
②对于infile,使用getline函数逐行读取文件,将文件的每个单词在map_file中查找,若找到则用map_file中的value将其替代,最后输出。注:输出空格的细节!
知识点总结:
1.main函数的形参
main(int argc, char **argv);
argc是一个整型变量,指的是命令行输入参数的个数,argv是字符串数组,它包含argc个字符串,每个字符串存储着一个命令行参数,其也可以写作char *argv[]。
如该例子argv[0]存储的是命令名,argv[1],argv[2]存储着执行该程序所需要的两个文件名参数。
argc和argv就是一个名字,可以改变的,如写成arc和arv,丝毫不影响。
对形参个数的检查:
if(argc != 3) throw runtime_error("Wrong number of arguments!");
2.文件打开
ifstream& open_file(ifstream &in, const string &file ) { in.close(); in.clear(); in.open ( file.c_str() );//open the file we were given return in; }
输入的两个参数:文件流和文件名
最后要么将in和指定文件绑在了一起,要么处于错误条件状态。
错误使用throw runtime_error
3.文件读取
对于文件1,将输入的文件中的单词转换对使用make_pair创建pair对象trans_map。
再用insert函数,如果key不存在,则添加。
while (map_file >>key >>value) trans_map.insert(make_pair(key, value));
对于文件2,首先使用getline逐行读入,istringstream对象可以绑定一行字符串,然后以空格为分隔符把该行分隔开来。
(例:
stringstream strm(s); //创建存储s的副本的 stringstream 对象,其中 s 是 string 类型的对象
)
while ( getline(input, line)) //read a line from the input to line
{ istringstream stream(line); string word; bool firstword = true; while (stream >>word) { /*Use word find the key of trans_map*/ map<string, string>::const_iterator map_it = trans_map.find(word); if (map_it !=trans_map.end()) /*if there is substitute for word, change the word*/ word = map_it->second; if (firstword) firstword = false; else cout << " "; cout << word; } cout << endl; }
从输入文件中一个个读入单词word,如果能在trans_map的key中找到,则将word更改为trans_map的value值,循环录入,使用迭代器:
map<string, string>::const_iterator map_it = trans_map.find(word);
最后输出word。
答案中还考虑了空格的录入,但是为什么不直接输出cout << word<<" "; ??
if (firstword) firstword = false; else cout << " ";
4.技术小白的一点收获
知道了怎么向main函数传递参数:
通过 项目---属性---配置属性---调试---命令参数惊醒main函数参数的添加,各个参数之间以空格隔开;注意此时添加进去的参数被依次保存为argv[1]、argv[2]……
argc也相应进行的增加,其中第一个参数argv[0]是编译器自动传入的生成的.exe所在的路径。之后在main函数中可以通过printf把已经传入的参数个数和相应的参数内容打印出来,此时的参数类型都是字符串类型的,如果需要要进行相应的类型转化。
当然还有Dos的方法,
“运行”->cmd->d:\e\f.exe g1 g2 g3......
不过为嘛不可以???待解?