前面的话:C++Primer并不适合“初学者”,初学者还是看《C++Primer Plus》我没有看过,但道听途说适合初学者,学习C++的艰辛真是一言难尽!
其实《C++Primer》这本书我一直在看,来来回回,反反复复,因为心浮气躁所以收效不大,其实如果你自认为是理所当然的事情其实你可能并不知道地很清楚,所以我决心从头再看一遍,我要把里面的程序和习题从头到尾彻彻底底地执行和剖析一遍,并写下心得和笔记,之所以这样一个是为我自己,一个是为了因为学习C++ Primer而非常痛苦的人们,我曾经听过一位博士讲的C++课程,我感觉是在浪费宝贵的时间,因为根据我的经验,往往是教材的每章的最后部分才是实际中最有用的部分,而在学校里就被略过了,因为考试不会考。因为是自学,所以在遇到问题时往往没有人给你回答,网路上的C++ Primer学习笔记太过简略,没有多大的价值,在第五章之前,我一直没有遇到太大的疑问,我跳过了第二章,在学完了后面的章节,才有资格去看第二章。为了更好的剖析C++ Primer,我手上的参考书籍是,在遇到问题时我都会翻看以下这些书籍:
《The C++ Programming Language》by Bjarne Stroustrup
《The C++ Standard Library》by Nicolai M.Josuttis
《effective C++》by Mayer
《More effective C++》by Mayer
《C++ STL 中文版》by P.J.Plauger
《掌握标准C++类》by Cameron Hughes ,Tracey Hughes
《STL 进行C++编程》by David etc
《Think in C++》by Bruce
《C++ 大学教程》by H.M ,P.D
......
......
......
第五章:
ilist类的编译
第○,改.c为.cpp;
第一,应该把#include “iostream.h”全部改成“ #include "iostream",同样
fstream.h -> fstream; stddef.h -> cstddef ,对于别的程序可能要附加相应的
文件头,这要看程序使用了什么特色了;
第二,增加using namespace std到预处理器后面;
第三,去掉 allocator
第四,g++ -o ilist.exe ilist.cpp ilistmain.cpp ;
成功了!
5.11 P202,关于_current
_current是指向一个ilist_item类的指针,意义是总是指向当前的活动的ilist_item项,如果删除了ilist的头,而_current还是指向链表头那就大事不妙了,所以对remove和remove_front要进行修改。
第六章
main0.cpp程序的注释
//增加#include <iterator>到程序头
//在运行栏输入:g++ -o main0.exe main0.cpp
#include <algorithm>
#include <string>
#include <vector>
#include <utility>
#include <iostream>
#include <fstream>
#include <iterator> //因为运用了ostream_iterator模板对象所以这是必须的,而原程序没有包含
#include <cstddef>
#include <ctype.h>
using namespace std; //为了方便,所以显式指定名字空间是标准名字空间
extern vector<string> *retrieve_text(); //这句是说retrieve_text在某处已经定义了,让编译程序自己去找,main会用到
int main()
{
vector<string> *text_file = retrieve_text(); //text_file是指向一个由string组成的vector的指针,由retrieve_text返回
cout << "----------- about to generate text read --------------/n";
ostream_iterator< string > output( cout, "/n" ); //这句是说output是一个输出流迭代器,此迭代器锁定了string类型,与cout标准输出对象绑定,大部分情况下是显示器,对于读到的每一行都插入/n 换行符
copy( text_file->begin(), text_file->end(), output );//拷贝所有的text_file到标准输出,换句话说就是把text_file插入到标准输出
return 0;
}
//我先大体的叙述一下retrieve_text函数是做什么和怎么做的,此函数读取输入的文本文件中的每一行,一行一行地记录其内容,为什么这么说呢,你想想看-它把输入的文本文件一行一行的读出来,看做string,用push_back放在了vector中,简言之vector中的0号元素就是text文件的第一行,以此类推。
它是如何做的呢?首先它构建了一个ifstream对象,这个对象的本身代表输入文本文件自己,接着getline登场,注意getline有两个一个是为流提供的getline,一个是在<string>中为string提供的getline,此处用的是后者。getline顾名思义,就是得到文件的一行,其实那倒也不一定,取决于getline的第三个参数,默认的参数就是“/n",“/n"意味着getline就是名副其实的get line,接下来vector的push_back粉墨登场,它把从getline获取的每一行做为string放进vector容器中,此时vector的大小会自动的加一。其它的部分很简单,就此略过。
vector<string>*
retrieve_text()
{
string file_name;
cout << "please enter file name: ";
cin >> file_name;
ifstream infile( file_name.c_str(), ios::in );//infile是一个ifstream //对象,当然ifstream是一个由typedef定义的模板类,它锁定了char类型做为参量,构造函数需要一个const char*,ios::in的意义是首先ios是一个锁定char类型的流模板,而in是告诉流要为输入而打开一个文件
if ( !infile ) {
cerr << "oops! unable to open file "
<< file_name << " -- bailing out!/n";
exit( -1 );
}
else if( infile.eof() ){
//我自己的修改,如果输入的文本文件是空的,则退出不做这样的处理会在这样的情况下崩溃
cerr << "please don't input a empty file";
cout << "/n";
exit( -1 );
}
vector<string> *lines_of_text = new vector<string>;
string textline;
typedef pair<string::size_type, int> stats;
stats maxline;
int linenum = 0;
while ( getline( infile, textline, '/n' ))
{
cout << "line read: " << textline << "/n";
if ( maxline.first < textline.length() )
{
maxline.first = textline.length();
maxline.second = linenum;
}
lines_of_text->push_back( textline );
linenum++;
}
cout << "/n";
cout << "number of lines: "
<< lines_of_text->size() << "/n";
cout << "maximum length: "
<< maxline.first << "/n";
cout << "longest line: "
<< (*lines_of_text)[ maxline.second ] << "/n";
return lines_of_text;
}
/*
dumbo[107] ~/d.stdlib => a.out
please enter file name: alice_emma
line read: Alice Emma has long flowing red hair. Her Daddy says
line read: when the wind blows through her hair, it looks almost alive,
line read: like a fiery bird in flight. A beautiful fiery bird, he tells her,
line read: magical but untamed. "Daddy, shush, there is no such thing,"
line read: she tells him, at the same time wanting him to tell her more.
line read: Shyly, she asks, "I mean, Daddy, is there?"
number of lines: 6
maximum length: 66
longest line: like a fiery bird in flight. A beautiful fiery bird, he tells her,
main1.cpp程序的注释
#include <algorithm>
#include <string>
#include <vector>
#include <utility>
#include <iterator>
#include <iostream>
#include <fstream>
#include <cstddef>
using namespace std;
typedef pair<short,short> location;
typedef vector<location> loc;
typedef vector<string> text;
typedef pair<text*,loc*> text_loc;
extern vector<string> *retrieve_text();
extern text_loc *separate_words( const vector<string>* );
extern void display_text_locations( text_loc* );
int main()
{
vector<string> *text_file = retrieve_text();
text_loc *text_locations = separate_words( text_file );
ostream_iterator< string > output( cout, "/n" );
cout << "----------- about to generate text read --------------/n";
copy( text_file->begin(), text_file->end(), output );
cout << "----------- about to word and location data --------------/n";
display_text_locations( text_locations );
return 0;
}
vector<string>*
retrieve_text()
{
string file_name;
cout << "please enter file name: ";
cin >> file_name;
ifstream infile( file_name.c_str(), ios::in );
if ( !infile ) {
cerr << "oops! unable to open file "
<< file_name << " -- bailing out!/n";
exit( -1 );
}
else cout << "/n";
vector<string> *lines_of_text = new vector<string>;
string textline;
typedef pair<string::size_type, int> stats;
stats maxline;
int linenum = 0;
while ( getline( infile, textline, '/n' ))
{
cout << "line read: " << textline << "/n";
if ( maxline.first < textline.length() )
{
maxline.first = textline.length();
maxline.second = linenum;
}
lines_of_text->push_back( textline );
linenum++;
}
cout << "/n";
cout << "number of lines: "
<< lines_of_text->size() << "/n";
cout << "maximum length: "
<< maxline.first << "/n";
cout << "longest line: "
<< (*lines_of_text)[ maxline.second ] << "/n";
return lines_of_text;
}
text_loc*
separate_words( const vector<string> *text_file )
{
// ok: now have all the lines. wish to grab the
// individual words: look for blanks:
vector<string> *words = new vector<string>;
vector<location> *locations = new vector<location>;
//对于书中给出的输入文本文件text_file->size()应该是6,因为string vector就是6行
//所以对于for循环就是for(short line_pos = 0;line_pos < 6; line_pos++),共循环6次来迭
//代每一行
for ( short line_pos = 0; line_pos < text_file->size(); line_pos++ )
{
short word_pos = 0;
string textline = (*text_file)[ line_pos ];
cout << "textline: " << textline << endl;
string::size_type eol = textline.length(); //这是一行的长度,连空格和符号也别放过
string::size_type pos = 0, prev_pos = 0;
//好的,现在让我们开始数数儿吧。
while (( pos = textline.find_first_of( ' ', pos )) != string::npos )
{
// 例如:对于第一行 :Alice Emma has long flowing red hair. Her Daddy says
// eol: 52 pos: 5 line: 0 word: 0 substring: Alice 意思是说,数到52,第一行结束,数到第5时
//出现个空格(记住Lippman先生说过要从0开始数),是第0行,此时标记出第一个词,
//位置是0,内容是Alice,再把Alice放进words中,words是一个string vector,想想为什么
//要放进vector中,因为要给单独的词一个代号比如0号,1号,2号.......
cout << "eol: " << eol << " "
<< "pos: " << pos << " "
<< "line: " << line_pos << " "
<< "word: " << word_pos << " "
<< "substring: "
<< textline.substr( prev_pos, pos-prev_pos )
<< "/n";
words->push_back( textline.substr( prev_pos, pos - prev_pos ));
//locations是一个pair vector,执行完此句locations就变成{(0, 0)......}了
locations->push_back( make_pair( line_pos, word_pos ));
word_pos++; pos++; prev_pos = pos;
}
cout << "last word on line substring: "
<< textline.substr( prev_pos, pos-prev_pos )
<< "/n";
words->push_back( textline.substr( prev_pos, pos - prev_pos ));
locations->push_back( make_pair( line_pos, word_pos ));
}
return new text_loc( words, locations ); //( Alice, (0, 0) ) ........
}
// text_loc是一个( vector<string>*, vector<pair(short,short) >) pair
// display_text_locations首先分离出words和locations,先判断两者的匹配情况
// 因为每对应一个word就应该有一个location,简言之,就是一个对一个,因为它们都是
// vector
void
display_text_locations( text_loc *text_locations )
{
vector<string> *text_words = text_locations->first;
vector<location> *text_locs = text_locations->second;
register int elem_cnt = text_words->size();
if ( elem_cnt != text_locs->size() )
{
cerr << "oops! internal error: word and position vectors "
<< "are of unequal size/n"
<< "words: " << elem_cnt << " "
<< "locs: " << text_locs->size()
<< " -- bailing out!/n";
exit( -2 );
}
for ( int ix = 0; ix < elem_cnt; ix++ )
{
cout << "word: " << (*text_words)[ ix ] << "/t"
<< "location: ("
<< (*text_locs)[ix].first << ","
<< (*text_locs)[ix].second << ")"
<< "/n";
}
cout << endl;
}
main2.cpp
void
filter_text( vector<string> *words, string filter )
{
vector<string>::iterator iter = words->begin();
vector<string>::iterator iter_end = words->end();
if ( ! filter.size() )
filter.insert( 0, "/".," );
cout << "filter elements: " << filter << endl;
while ( iter != iter_end )
{
cout << "filter_text: " << *iter << endl;
string::size_type pos = 0;
//find_first_of如果没有找到匹配的项会返回string::npos所以可以用string::npos做为标志
while (( pos = (*iter).find_first_of( filter, pos )) != string::npos )
{
cout << "found! : pos: "
<< pos << "/t"
<< (*iter)[pos] << endl;
// this is wrong: erases from pos to npos
// (*iter).erase(pos);
(*iter).erase(pos,1);
cout << "after: " << *iter << endl;
}
cout << "finished with word: " << *iter << endl;
iter++;
}
}