文章目录
1
1.1 分割字符串
//分离字符串
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cctype>
using std::cin; using std::cout;
using std::endl;
using std::string; using std::vector;
using std::find_if;
//是空白区域为true
bool space(char c){
return isspace(c);
}
//不是空白区域为true
bool not_space(char c){
return !isspace(c);
}
vector<string> split2(const string& str){
typedef string::const_iterator iter;
vector<string> ret;
iter i = str.begin();
while(i != str.end()){
//忽略前面的空白
i = find_if(i, str.end(), not_space);
//找到下一个单词的结尾
iter j = find_if(i , str.end(), space);
//复制在[i,j)中的字符
if(i != str.end()){
ret.push_back(string(i, j));
}
i = j;
}
return ret;
}
//分割字符串
vector<string> split(const string& s){
vector<string> ret;
typedef string::size_type string_size;
string_size i = 0;
while(i != s.size()){
//忽略前段的空白:[先前的i,i)中全部字符都是空格
while(i != s.size() && isspace(s[i])){
i++;
}
//找出下一个单词的终结点
string_size j = i;
//[先前的j,j)中的任意字符都不是空格
while(j != s.size() && !isspace(s[j])){
j++;
}
//找到了一些非空白符
if(i != j){
ret.push_back(s.substr(i, j - i));
i = j;
}
}
return ret;
}
int main(int argc, char const *argv[]){
string s;
while(cin >> s){
vector<string> v = split(s);
for (vector<string>::size_type i = 0; i != v.size(); ++i) {
cout << v[i] <<endl;
}
}
return 0;
}
1.2 判回文
//判回文
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using std::cin; using std::cout;
using std::endl;
using std::string; using std::vector;
using std::equal;
bool is_pailndrome(const string& s){
//s.rbegin()返回最后一个元素,并逆向向前访问
return equal(s.begin(), s.end(), s.rbegin());
//第一、二个参数为第一个序列,第三个参数无诶第二序列的起点
}
int main(int argc, char const *argv[]){
string s;
while(cin >> s){
if(is_pailndrome(s)){
cout << "Yes" <<endl;
}else{
cout <<"No" <<endl;
}
}
return 0;
}
1.3 寻找URL
//找统一资源地址
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cctype>
using std::cin; using std::cout;
using std::endl;
using std::string; using std::vector;
using std::equal; using std::search;
using std::find_if;
//没找到字符,返回true
bool not_url_char(char c){
//除数字字母外可能,其他可能出现的URL中的字符
static const string url_ch = "~;!@#$%^&*()_+/'?.=&-:";
//查看c是够出现在一个URl中并返回求反的值
return !(isalnum(c)|| find(url_ch.begin(), url_ch.end(),c) != url_ch.end());
}
string::const_iterator url_end(string::const_iterator b, string::const_iterator e){
return find_if(b, e, not_url_char);
}
string::const_iterator url_beg(string::const_iterator b, string::const_iterator e){
static const string sep = "://";
typedef string::const_iterator iter;
//i标记了查找到的分隔符的位置
iter i = b;
i = search(i ,e , sep.begin(), sep.end());
//如果找到会返回//之前的位置,没有找到会返回输入字符串的末尾之后的那个位置
while(i != e){
//分隔符是否填满整行,://前面有字符串以及://后面至少有一个字符
if(i != b && i + sep.size() != e){
//beg标记协议名称的开头
iter beg = i;
//一直碰到第一个非字母或者字符串开头为止
while(beg != b && isalpha(beg[-1])){
--beg;
}
//是够在分隔符前面以及后面至少有一个字符
if(beg != i && !not_url_char(i[sep.size()])){
return beg;
}
}
//找到的分割符不是URL的一部分
i += sep.size();
}
return e;
}
vector<string> find_urls(const string& s){
vector<string> ret;
typedef string::const_iterator iter;
iter b = s.begin(), e = s.end();
//检查整个输入
while(b != e){
//查找下一个或多个紧跟着://的字母
b = url_beg(b, e);
//查找成功
if(b != e){
//获取url其余部分
iter after = url_end(b, e);
//记住这个url
ret.push_back(string(b,after));
//将b向前推进并查找本行中的其他url
b = after;
}
}
return ret;
}
int main(int argc, char const *argv[]){
string s;
// while(cin >> s){
cin >> s;
vector<string> res = find_urls(s);
for (vector<string>::const_iterator it = res.begin(); it != res.end(); ++it) {
cout << (*it) << endl;
}
// }
return 0;
}
1.4 计算成绩
头文件
grade.h
#ifndef ACM_GRADE_H
#define ACM_GRADE_H
#include<vector>
#include"Student_info.h"
double grade(double, double, double);
double grade(double, double, const std::vector<double>&);
double grade(const Student_info&);
#endif
Student_info.h
#ifndef ACM_Student_info
#define ACM_Student_info
#include <iostream>
#include <string>
#include <vector>
struct Student_info{
std::string name;
double midterm, final;
std::vector<double> homework;
// double score;
};
bool compare(const Student_info&, const Student_info&);
bool fgrade(const Student_info&);
std::istream& read_hw(std::istream&, std::vector<double>&);
std::istream& read(std::istream&, Student_info&);
#endif
#include <iostream>
#include <algorithm>
#include <vector>
#include "Student_info.h"
#include "grade.h"
#include <stdexcept>
#include <numeric>
#include <string>
#include <ostream>
using std::cin; using std::cout;
using std::endl;
using std::vector; using std::transform;
using std::domain_error; using std::string;
using std::ostream; using std::transform;
using std::istream;
bool did_all_hw(const Student_info& s){
return ((find(s.homework.begin(), s.homework.end(),0)) == s.homework.end());
}
//求中位数
double median(vector<double> vec){
typedef vector<double>::size_type vec_sz;
vec_sz size = vec.size();
if(size == 0)
throw domain_error ("median of an empty vector");
sort(vec.begin(), vec.end());
vec_sz mid = size/2;
return size % 2 == 0 ? (vec[mid] + vec[mid-1])/2 : vec[mid];
}
//对Stundet_info类型的对象进行处理
double grade(const Student_info& s){
return grade(s.midterm, s.final, s.homework);//调用grade2
}//grade1
//根据期中、期末以及保存家庭作业的向量来计算学生的总成绩
double grade(double midterm, double final, const vector<double>& hw){
if(hw.size() == 0)
throw domain_error("student has done no homework");
return grade(midterm, final, median(hw));//如果家庭作业非空,则调用grade3
}//grade2
//根据期中、期末、平时成绩计算总成绩
double grade(double midterm, double final, double homework){
return 0.2 * midterm + 0.4 * final + 0.4 * homework;
}//garde3
//重写便于transform调用,解决学生家庭成绩为0 的情况
double grade_aux(const Student_info& s){
try{
return grade(s);
}catch (domain_error){
return grade(s.midterm, s.final, 0);
}
}
double median_analysis(const vector<Student_info>& students){
vector<double > grades;
transform(students.begin(), students.end(), back_inserter(grades), grade_aux);
return median(grades);
}
//计算向量平均值
double average(const vector<double >& v){
return accumulate(v.begin(), v.end(), 0) / v.size();
}
//计算单个学生成绩,用平均值代替中值
double average_grade(const Student_info& s){
return grade(s.midterm, s.final, average((s.homework)));
}
//计算家庭作业平均成绩的总成绩
double average_analysis(const vector<Student_info>& students){
vector<double > grades;
transform(students.begin(), students.end(), back_inserter(grades), average_grade);
return median(grades);
}
//计算单个学生成绩,计算实际上交作业的中值
double optimistic_median(const Student_info& s){
vector<double > nonzero;
std::remove_copy(s.homework.begin(), s.homework.end(), back_inserter(nonzero), 0);
if(nonzero.empty()){
return grade(s.midterm, s.final, 0);//学生一次作业都没有做
}else{
return grade(s.midterm, s.final, median(nonzero));
}
}
//计算乐观成绩中值
double optimistic_median_analysis(const vector<Student_info>& students){
vector<double > grades;
transform(students.begin(), students.end(), back_inserter(grades), optimistic_median);
return median(grades);
}
//读入学生姓名、期中、期末成绩、家庭作业成绩
istream& read(istream& is, Student_info& s){
is >> s.name >> s.midterm >> s.final;
//如果输入的期中、期末成绩不是数字,则会把输入流标记为失败状态
read_hw(is, s.homework);//读入家庭作业
return is;
}
//从输入流中将家庭作业的成绩读入到一个vector<double>中
istream& read_hw(istream& in, vector<double>& hw){
if(in){//当前学生的姓名、期中期末成绩非法时(输入流标记为失败状态),不会读入家庭作业
//清除原先内容
hw.clear();//清除之前可能存在的成绩,重新再次拥有空向量
double x;
while(in >> x){//输入的不是成绩时,库把输入流标记为失败状态
hw.push_back(x);
}
//清除流使得输入动作对下个学生有效
in.clear();//清除所有错误标记使得输入动作可以继续,并不清除下一个存储在输入流中的姓名
}//如正常读完in,则返回in正确标记
return in;
}
//函数作为参数传递,分析比较两个学生的集合,全做家庭作业的和漏交家庭作业的
void write_analysis(ostream& out, const string& name,
double analysis(const vector<Student_info>&), const vector<Student_info>&did,
const vector<Student_info>& didnt){
out << name <<":median(did) = " << analysis(did)
<<",median(didnt) = " << analysis(didnt) << endl;
}
int main(int argc, char const *argv[]){
vector<Student_info> did, didnt;
Student_info student;
while(read(cin, student)){
if(did_all_hw(student)){
did.push_back(student);
}else{
didnt.push_back(student);
}
}
if(did.empty()){
cout << "No students did all the homework!" <<endl;
return 1;
}
if(didnt.empty()){
cout << "Every student did all the homeword!" <<endl;
}
write_analysis(cout, "median", median_analysis, did, didnt);
write_analysis(cout, "average", average_analysis, did, didnt);
write_analysis(cout, "median of homework truned in", optimistic_median_analysis, did, didnt);
return 0;
}
1 使用迭代器重新实现frame函数和hcat函数
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <algorithm>
#include <cctype>
using std::cin; using std::endl;
using std::cout; using std::string;
using std::vector; using std::max;
//分割字符串
vector<string> split(const string& s){
vector<string> ret;
typedef string::size_type string_size;
string_size i = 0;
while(i != s.size()){
//忽略前段的空白:[先前的i,i)中全部字符都是空格
while(i != s.size() && isspace(s[i])){
i++;
}
//找出下一个单词的终结点
string_size j = i;
//[先前的j,j)中的任意字符都不是空格
while(j != s.size() && !isspace(s[j])){
j++;
}
//找到了一些非空白符
if(i != j){
ret.push_back(s.substr(i, j - i));
i = j;
}
}
return ret;
}
//找出向量中最长字符串的长度
string::size_type width(const vector<string>& v){
string::size_type maxlen = 0;
for (vector<string>::size_type i = 0; i != v.size(); ++i) {
maxlen = max(maxlen, v[i].size());
}
return maxlen;
}
vector<string> frame(const vector<string>& v){
vector<string> ret;
string::size_type maxlen = width(v);
//输出顶部边框
string border(maxlen + 4, '*');
//输出内部的行,每行都用一个星号和一个空格来框起来
ret.push_back(border);
//使用迭代器实现
vector<string>::const_iterator iter = v.begin();
while(iter != v.end()){
ret.push_back("* " + (*iter) + string(maxlen - iter->size(), ' ') + " *");
iter++;
}
//
// for (vector<string>::size_type i = 0; i != v.size(); ++i) {
// ret.push_back("* "+ v[i] + string(maxlen - v[i].size(), ' ') + " *");
// }
//输出底部边框
ret.push_back(border);
return ret;
}
//纵向连接
vector<string> vcat(const vector<string>& top, const vector<string>& bottom){
vector<string> ret = top;
// for (vector<string>::const_iterator it = bottom.begin(); it != bottom.end() ; ++it) {
// ret.push_back(*it);
// }
//作用同上
ret.insert(ret.end(), bottom.begin(), bottom.end());
return ret;
}
//横向连接
vector<string> hcat(const vector<string>& left, const vector<string>& right){
vector<string>ret;
//在两幅图案之间留空格
string::size_type width1 = width(left) + 1;
//用于遍历left和right的索引
//使用迭代器
vector<string>::const_iterator i, j;
i = left.begin();
j = right.begin();
while(i != left.end() || j != right.end()){
string s;
if(i != left.end()){
s = *i++;
}
s += string(width1 - s.size(), ' ');
if(j != right.end()){
s += *j++;
}
ret.push_back(s);
}
// vector<string>::size_type i = 0, j = 0;
// while(i != left.size() || j != right.size()){
// string s;
// //如果左侧图案还有待复制的行,则复制一行
// if(i != left.size()){
// s = left[i++];
// }
// //填充至适当长度
// s += string(width1 - s.size(), ' ');
// //如果右侧还有代复制的行,则复制一行
// if(j != right.size()){
// s += right[j++];
// }
// ret.push_back(s);
// }
return ret;
}
int main(int argc,const char *argv[]){
string s;
while(getline(cin, s)){
vector<string> v = split(s);
// for (vector<string>::size_type i = 0; i != v.size(); ++i) {
// cout << v[i] <<endl;
// }
vector<string> fra = frame(v);
vector<string> col, row;
col = vcat(v, fra);
row = hcat(v, fra);
//打印竖着拼图
// for (vector<string>::size_type i = 0; i != col.size(); ++i) {
// cout << col[i] << endl;
// }
// //打印横向拼图
for (vector<string>::size_type j = 0; j != row.size(); ++j) {
cout << row[j] <<endl;
}
}
return 0;
}
2 编程并测试find_urls函数
//找统一资源地址
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cctype>
using std::cin; using std::cout;
using std::endl;
using std::string; using std::vector;
using std::equal; using std::search;
using std::find_if;
//没找到字符,返回true
bool not_url_char(char c){
//除数字字母外可能,其他可能出现的URL中的字符
static const string url_ch = "~;/?:@=&$-_.+!*'(),";
//查看c是够出现在一个URl中并返回求反的值
return !(isalnum(c)|| find(url_ch.begin(), url_ch.end(),c) != url_ch.end());
}
string::const_iterator url_end(string::const_iterator b, string::const_iterator e){
return find_if(b, e, not_url_char);
}
string::const_iterator url_beg(string::const_iterator b, string::const_iterator e){
static const string sep = "://";
typedef string::const_iterator iter;
//i标记了查找到的分隔符的位置
iter i = b;
i = search(i ,e , sep.begin(), sep.end());
//如果找到会返回//之前的位置,没有找到会返回输入字符串的末尾之后的那个位置
while(i != e){
//分隔符是否填满整行,://前面有字符串以及://后面至少有一个字符
if(i != b && i + sep.size() != e){
//beg标记协议名称的开头
iter beg = i;
//一直碰到第一个非字母或者字符串开头为止
while(beg != b && isalpha(beg[-1])){
--beg;
}
//是够在分隔符前面以及后面至少有一个字符
if(beg != i && !not_url_char(i[sep.size()])){
return beg;
}
}
//找到的分割符不是URL的一部分
i += sep.size();
}
return e;
}
vector<string> find_urls(const string& s){
vector<string> ret;
typedef string::const_iterator iter;
iter b = s.begin(), e = s.end();
//检查整个输入
while(b != e){
//查找下一个或多个紧跟着://的字母
b = url_beg(b, e);
//查找成功
if(b != e){
//获取url其余部分
iter after = url_end(b, e);
//记住这个url
ret.push_back(string(b,after));
//将b向前推进并查找本行中的其他url
b = after;
}
}
return ret;
}
int main(int argc, char const *argv[]){
string s;
// while(cin >> s){
cin >> s;
vector<string> res = find_urls(s);
for (vector<string>::const_iterator it = res.begin(); it != res.end(); ++it) {
cout << (*it) << endl;
}
// }
return 0;
}
3 观察下面程序段的用途
用途是:定义一个长度为0,初值为100的向量u(实际上向量u没有任何一个元素),把u中的元素复制到向量v中,但是由于v.begin()不是向量适配器,无法向容器插入值,导致复制失败。就算u中有值,但是下面示例中的copy还是无法将其复制到v中。
#include <iostream>
using std::cin; using std::endl;
using std::cout;
#include <vector>
using std::vector;
#include <algorithm>
using std::copy;
int main(int argc,const char *argv[]){
vector<int> u(0, 100);
//vector<int> u(10, 100);
vector<int> v;
copy(u.begin(), u.end(), v.begin());
for (vector<int>::const_iterator i = v.begin(); i != v.end(); ++i) {
cout << *i << endl;
}
return 0;
}
4 改进3的程序,使之可以是想操作
#include <iostream>
using std::cin; using std::endl;
using std::cout;
#include <vector>
using std::vector;
#include <algorithm>
using std::copy;
#include <iterator>
using std::back_inserter;
using std::inserter;
int main(int argc,const char *argv[]){
// vector<int> u(0, 100);
vector<int> u(1, 100);
vector<int> v;
//有元素的情况可以插入
// vector<int> v(1,11);
// copy(u.begin(), u.end(), v.begin());
//使用迭代器适配器
//改进方法一
//copy(u.begin(), u.end(), back_inserter(v));
//改进方法二
copy(u.begin(), u.end(), inserter(v,v.end()));
for (vector<int>::const_iterator i = v.begin(); i != v.end(); ++i) {
cout << *i << endl;
}
return 0;
}
5
//计算乐观成绩中值
double optimistic_median_analysis(const vector<Student_info>& students){
vector<double > grades;
transform(students.begin(), students.end(), back_inserter(grades), optimistic_median);
return median(grades);
}
分析函数
//函数作为参数传递,分析比较两个学生的集合,全做家庭作业的和漏交家庭作业的
void write_analysis(ostream& out, const string& name,
double analysis(const vector<Student_info>&), const vector<Student_info>&did,
const vector<Student_info>& didnt){
out << name <<":median(did) = " << analysis(did)
<<",median(didnt) = " << analysis(didnt) << endl;
}
6 把三个分析函数合并成一个单独的函数
也就是把函数作为参数传递给analysis。
double analysis(const vector<Student_info>& students, double grade_deal(const Student_info&)){
vector<double > grades;
transform(students.bebgin(), students.end(), back_inserter(grades), grade_deal);
return median(grades);
}
下面是三个分析函数,每个分析函数除了transform调用的处理函数不同外,其他都相同。
//计算单个学生成绩,计算实际上交作业的中值
double optimistic_median(const Student_info& s){
vector<double > nonzero;
std::remove_copy(s.homework.begin(), s.homework.end(), back_inserter(nonzero), 0);
if(nonzero.empty()){
return grade(s.midterm, s.final, 0);//学生一次作业都没有做
}else{
return grade(s.midterm, s.final, median(nonzero));
}
}
//计算乐观成绩中值
double optimistic_median_analysis(const vector<Student_info>& students){
vector<double > grades;
transform(students.begin(), students.end(), back_inserter(grades), optimistic_median);
return median(grades);
}
//计算单个学生成绩,用平均值代替中值
double average_grade(const Student_info& s){
return grade(s.midterm, s.final, average((s.homework)));
}
//计算家庭作业平均成绩的总成绩
double average_analysis(const vector<Student_info>& students){
vector<double > grades;
transform(students.begin(), students.end(), back_inserter(grades), average_grade);
return median(grades);
}
//重写便于transform调用,解决学生家庭成绩为0 的情况
double grade_aux(const Student_info& s){
try{
return grade(s);
}catch (domain_error){
return grade(s.midterm, s.final, 0);
}
}
double median_analysis(const vector<Student_info>& students){
vector<double > grades;
transform(students.begin(), students.end(), back_inserter(grades), grade_aux);
return median(grades);
}
double analysis(const vector<Student_info>& students, double grade_deal(const Student_info&)){
vector<double > grades;
transform(students.bebgin(), students.end(), back_inserter(grades), grade_deal);
return median(grades);
}
7
bool did_all_hw(const Students_info& s){
return ((find(s.homework.begin(), s.homework.end(), 0)) == s.homework.end());
}
int test_extract(string file){
vector<Students_info> did, didnt;
Student_info student;
iftream infile;
infile.open(file);
while(read(infile, student)){
if(did_all_hw(student)){
did.push_back(student);
}else{
didnt.push_back(student);
}
}
infile.close();
infile.clear();
if(did.empty()){
cout << "No students did all the homework!" <<endl;
return 1;
}
if(didnt.empty()){
cout << "Every student did all the homeword!" <<endl;
}
}
8 按照自己的准则分类学生
更改bool类型函数已实现不同的分类:
bool fgrade (const Student_info& s){
return grade(s) < 90;
}
//students保存成绩90分以上的学生,fail保留余下的学生
vector<Student_info> extrac_fail3(vector<Student_info>& students){
vector<Student_info> fail;
vector<Student_info>::iterator iter = students.begin();
while(iter != students.end()){
if(fgrade(*iter)){
fail.push_back(*iter);
iter = students.erase(iter);
}else{
++iter;
}
}
return fail;
}
9 使用库算法连接一个vector<string>对象中的全部元素
#include <iostream>
using std::cin; using std::endl;
using std::cout;
#include <vector>
using std::vector;
#include <string>
using std::string;
#include <numeric>
using std::accumulate;
int main(int argc,const char *argv[]){
vector<string> v = {"i", "love", "you"};
string str;
str = accumulate(v.begin(), v.end(), str);
cout << str;
return 0;
}