2024年12月完成(补充提交)

This commit is contained in:
张梦南 2025-03-29 23:02:48 +08:00
commit 4e2bf47db0
39 changed files with 2106 additions and 0 deletions

7
Chapter 0/0-2.cpp Normal file
View File

@ -0,0 +1,7 @@
#include<iostream>
int main()
{
std::cout<<"This (\") is a quote , and this (\\) is a backlash."<<std::endl;
return 0;
}

15
Chapter 1/1-6.cpp Normal file
View File

@ -0,0 +1,15 @@
#include<iostream>
#include<string>
int main()
{
std::cout<<"What is your name? ";
std::string name;
std::cin>>name;
std::cout<<"Hello, "<<name
<<std::endl<<"And what is yours? ";
std::cin>>name;
std::cout<<"Hello, "<<name
<<"; nice to meet you too!"<<std::endl;
return 0;
}

50
Chapter 2/2-5.cpp Normal file
View File

@ -0,0 +1,50 @@
#include<iostream>
int main()
{
std::cout << "输入正方形的边长:";
float a, b, c, d;
std::cin >> a;
std::cout << "输入长方形的长和宽:";
std::cin >> b >> c;
std::cout << "输入三角形的高:";
std::cin >> d;
std::cout << "正方形:" << std::endl;
for (int i = 0; i < a; i++) {
for (int j = 0; j < a; j++) {
if (i == a - 1 || i == 0 || j == a - 1 || j == 0) {
std::cout << "*";
}
else {
std::cout << " ";
}
}
std::cout << std::endl;
}
std::cout << "长方形:" << std::endl;
for (int i = 0; i < c; i++) {
for (int j = 0; j < b; j++) {
if (i == c - 1 || i == 0 || j == b - 1 || j == 0) {
std::cout << "*";
}
else {
std::cout << " ";
}
}
std::cout << std::endl;
}
std::cout << "三角形:" << std::endl;
for (int i = 0; i < d; i++) {
for (int j = 0; j <= i; j++) {
if (j == 0 || j == i || i == 0 || i == d - 1) {
std::cout << "*";
}
else {
std::cout << " ";
}
}
std::cout << std::endl;
}
}

13
Chapter 2/2-8.cpp Normal file
View File

@ -0,0 +1,13 @@
#include<iostream>
int main()
{
std::cout << "输入要计算的区间范围:";
float a, b, c;
c = 1;
std::cin >> a >> b;
for (float i = a; i < b; i++) {
c = i * c;
}
std::cout << c;
}

48
Chapter 3/3-3.cpp Normal file
View File

@ -0,0 +1,48 @@
#include<iostream>
#include<string>
#include<map>
int main()
{
std::cout << "请输入单词:" << std::endl;
std::string word;
std::map<std::string, int>word_data;
while (std::cin >> word)
word_data[word] = word_data[word] + 1;
std::map<std::string, int>::iterator mp_next = word_data.begin();
while (mp_next != word_data.end())
{
std::cout << mp_next->first << " 的出现次数:" << mp_next->second << std::endl;
mp_next++;
}
}
#include <iostream> // 引入标准输入输出流库
#include <string> // 引入字符串库
#include <map> // 引入map容器库
int main()
{
// 输出提示信息
std::cout << "请输入单词:" << std::endl;
std::string word; // 用于存储用户输入的单词
std::map<std::string, int> word_data; // 定义一个map容器key为单词value为单词出现次数
// 循环读取用户输入的单词,直到输入结束(如按 Ctrl+D
while (std::cin >> word)
word_data[word] = word_data[word] + 1; // 更新单词出现次数
// 定义一个迭代器用于遍历map中的所有元素
std::map<std::string, int>::iterator mp_next = word_data.begin();
// 遍历map并输出每个单词及其出现次数
while (mp_next != word_data.end())
{
std::cout << mp_next->first << " 的出现次数:" << mp_next->second << std::endl;
mp_next++; // 移动到下一个元素
}
return 0; // 程序结束
}

58
Chapter 4/4-5.cpp Normal file
View File

@ -0,0 +1,58 @@
#include<iostream>
#include<string>
#include<map>
int main()
{
int a = 0;
std::cout << "请输入单词:" << std::endl;
std::cout << "退出按ctrl+z后回车" << std::endl;
std::string word;
std::map<std::string, int>word_data;
while (std::cin >> word) {
word_data[word] = word_data[word] + 1;
a = a + 1;
}
std::map<std::string, int>::iterator mp_next = word_data.begin();
std::cout << "输入的单词个数:" << a << std::endl;
while (mp_next != word_data.end())
{
std::cout << mp_next->first << " 的出现次数:" << mp_next->second << std::endl;
mp_next++;
}
}
#include <iostream> // 引入标准输入输出流库
#include <string> // 引入字符串库
#include <map> // 引入map容器库
int main()
{
int a = 0; // 用于统计输入的单词总数
std::cout << "请输入单词:" << std::endl; // 提示用户输入单词
std::cout << "退出按ctrl+z后回车" << std::endl; // 提示用户如何结束输入
std::string word; // 定义一个字符串变量,用于存储单个单词
std::map<std::string, int> word_data; // 定义一个map容器key为单词value为单词出现的次数
// 循环读取用户输入的单词直到用户输入结束Ctrl+Z后回车
while (std::cin >> word) {
word_data[word] = word_data[word] + 1; // 更新单词出现次数若不存在则初始化为1
a = a + 1; // 每读取一个单词计数器加1
}
// 定义一个迭代器用于遍历map容器
std::map<std::string, int>::iterator mp_next = word_data.begin();
// 输出总的输入单词数量
std::cout << "输入的单词个数:" << a << std::endl;
// 遍历map容器输出每个单词及其出现次数
while (mp_next != word_data.end())
{
std::cout << mp_next->first << " 的出现次数:" << mp_next->second << std::endl; // 输出单词和对应次数
mp_next++; // 移动迭代器到下一个元素
}
return 0; // 程序结束
}

55
Chapter 4/4-7.cpp Normal file
View File

@ -0,0 +1,55 @@
#include<iostream>
int main()
{
double a, b = 0, c = 0;
std::cout << "请输入数据:" << std::endl << "退出按ctrl+z后回车" << std::endl;
while (std::cin >> a) {
b = b + a;
c++;
}
b = b / c;
std::cout << "平均数为:" << b << std::endl;
}
/*
CSDN资料
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
int main() {
vector<double> nums;
double num;
while (cin >> num)
nums.push_back(num);
cout << accumulate(nums.begin(), nums.end(), 0.0) / nums.size() << endl;
}
*/
#include <iostream> // 引入标准输入输出流库
#include <numeric> // 引入numeric库用于使用accumulate函数
#include <vector> // 引入vector容器库
using namespace std;
int main() {
vector<double> nums; // 定义一个动态数组,用于存储用户输入的数值
double num; // 用于接收用户输入的单个数值
// 循环读取用户输入的数值直到输入结束Ctrl+Z 或 Ctrl+D 后回车)
while (cin >> num)
nums.push_back(num); // 将输入的数值添加到vector中
// 使用accumulate计算vector中所有数值的总和并除以数值个数以计算平均值
// 初始值设为0.0,避免因类型推导导致整型初始值
cout << accumulate(nums.begin(), nums.end(), 0.0) / nums.size() << endl;
return 0; // 程序结束
}

View File

@ -0,0 +1,88 @@
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
#include "pics.h"
using std::cout;
using std::copy;
using std::endl;
using std::ostream_iterator;
using std::string;
using std::vector;
int main()
{
vector<string> p;
p.push_back("this is an");
p.push_back("example");
p.push_back("to");
p.push_back("illustrate");
p.push_back("framing");
ostream_iterator<string>ofile(cout, "\n");
copy(p.begin(), p.end(), ofile);
cout << endl;
vector<string> f = frame(p);
copy(f.begin(), f.end(), ofile); cout << endl;
vector<string> h = hcat(p,frame(p));
copy(h.begin(), h.end(), ofile);
cout << endl;
return 0;
}
#include <algorithm> // 引入标准算法库用于std::copy等算法
#include <iostream> // 引入标准输入输出流库
#include <iterator> // 引入迭代器库用于std::ostream_iterator
#include <string> // 引入字符串库
#include <vector> // 引入动态数组vector容器库
#include "pics.h" // 引入自定义头文件提供frame和hcat函数的声明
using std::cout; // 引入标准输出对象
using std::copy; // 引入标准拷贝算法
using std::endl; // 引入标准换行符
using std::ostream_iterator; // 引入输出流迭代器
using std::string; // 引入标准字符串类
using std::vector; // 引入标准向量类
int main()
{
// 定义一个存储字符串的vector并向其中添加多行字符串
vector<string> p;
p.push_back("this is an"); // 添加字符串到vector
p.push_back("example");
p.push_back("to");
p.push_back("illustrate");
p.push_back("framing");
// 定义输出流迭代器用于将vector内容输出到标准输出
ostream_iterator<string> ofile(cout, "\n");
// 输出vector p的内容到终端
copy(p.begin(), p.end(), ofile);
cout << endl; // 输出一个空行分隔内容
// 调用frame函数为vector p添加边框并返回新vector
vector<string> f = frame(p);
// 输出带边框的vector内容
copy(f.begin(), f.end(), ofile);
cout << endl; // 输出一个空行分隔内容
// 调用hcat函数将原始vector p与带边框的vector f水平连接
vector<string> h = hcat(p, frame(p));
// 输出水平连接后的vector内容
copy(h.begin(), h.end(), ofile);
cout << endl; // 输出一个空行分隔内容
return 0; // 程序结束
}

View File

@ -0,0 +1,108 @@
#include <algorithm>
#include <string>
#include <vector>
#include "pics.h"
using std::string;
using std::vector;
using std::max;
#ifdef _MSC_VER
//#include "../minmax.h"
#else
//using std::max;
#endif
string::size_type width(const vector<string>& v)
{
string::size_type maxlen = 0;
#ifdef _MSC_VER
for(std::vector<string>::size_type i = 0; i != v.size(); ++i)
#else
for(vector<string>::size_type i = 0; i != v.size(); ++i)
#endif
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, '*');
// write the top border
ret.push_back(border);
// write each interior row, bordered by an asterisk and a space
#ifdef _MSC_VER
for (std::vector<string>::size_type i = 0; i != v.size(); ++i) {
#else
for (vector<string>::size_type i = 0; i != v.size(); ++i) {
#endif
ret.push_back("* " + v[i] +
string(maxlen - v[i].size(), ' ') + " *");
}
// write the bottom border
ret.push_back(border);
return ret;
}
vector<string> vcat(const vector<string>& top,
const vector<string>& bottom)
{
// copy the `top' picture
vector<string> ret = top;
// copy entire `bottom' picture
#ifdef _MSC_VER
for (std::vector<string>::const_iterator it = bottom.begin();
#else
for (vector<string>::const_iterator it = bottom.begin();
#endif
it != bottom.end(); ++it)
ret.push_back(*it);
return ret;
}
vector<string>
hcat(const vector<string>& left, const vector<string>& right)
{
vector<string> ret;
// add 1 to leave a space between pictures
string::size_type width1 = width(left) + 1;
// indices to look at elements from `left' and `right' respectively
#ifdef _MSC_VER
std::vector<string>::size_type i = 0, j = 0;
#else
vector<string>::size_type i = 0, j = 0;
#endif
string s;
// continue until we've seen all rows from both pictures
while (i != left.size() || j != right.size()) {
// construct new `string' to hold characters from both pictures
//string s;
// copy a row from the left-hand side, if there is one
if (i != left.size())
s = left[i++];
// pad to full width
s += string(width1 - s.size(), ' ');
// copy a row from the right-hand side, if there is one
if (j != right.size())
s += right[j++];
// add `s' to the picture we're creating
ret.push_back(s);
}
return ret;
}

View File

@ -0,0 +1,17 @@
#ifndef GUARD_pics_h
#define GUARD_pics_h
#include <string>
#include <vector>
std::string::size_type width(const std::vector<std::string>& v);
std::vector<std::string> frame(const std::vector<std::string>& v);
std::vector<std::string> vcat(const std::vector<std::string>& top,
const std::vector<std::string>& bottom);
std::vector<std::string> hcat(const std::vector<std::string>& left,
const std::vector<std::string>& right);
#endif

238
Chapter 6/6.1.cpp Normal file
View File

@ -0,0 +1,238 @@
#include <iostream>
#include <string>
#include <vector> //动态数组
#include <list>
#include <algorithm>
#include <cctype>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::max;
vector<string> split(const string& s) { //分割字符串按空格分割成单词并存储在vector<string>中
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++;
}
ret.push_back(border);
return ret;
}
//纵向连接
vector<string> vcat(const vector<string>& top, const vector<string>& bottom) {
vector<string> ret = top;
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);
}
return ret;
}
int main(int argc, const char* argv[]) {
string s;
while (getline(cin, s)) {
vector<string> v = split(s);
vector<string> fra = frame(v); //调用frame对分割后的单词添加框架
vector<string> col, row;
col = vcat(v, fra);
row = hcat(v, fra); //通过hcat将分割文本和框架化文本并排显示并输出到屏幕上
for (vector<string>::size_type j = 0; j != row.size(); ++j) {
cout << row[j] << endl;
}
}
return 0;
}
#include <iostream> // 引入标准输入输出流库
#include <string> // 引入字符串库
#include <vector> // 引入动态数组vector容器库
#include <list> // 引入链表容器库(未使用)
#include <algorithm> // 引入算法库用于std::max
#include <cctype> // 引入字符处理函数库用于std::isspace
using std::cin;
using std::cout;
using std::endl;
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()) {
// 跳过空格
while (i != s.size() && isspace(s[i])) {
i++;
}
// 找到下一个单词的结束位置
string_size j = i;
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; // 初始化最大长度为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++;
}
ret.push_back(border); // 添加底部边框
return ret;
}
// 纵向连接两个字符串向量
vector<string> vcat(const vector<string>& top, const vector<string>& bottom) {
vector<string> ret = top; // 初始化结果为顶部向量
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; // 为左侧添加一个空格的宽度
vector<string>::const_iterator 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); // 将拼接后的字符串添加到结果
}
return ret;
}
int main(int argc, const char* argv[]) {
string s;
while (getline(cin, s)) {
// 按空格分割输入字符串
vector<string> v = split(s);
// 为分割后的字符串添加框架
vector<string> fra = frame(v);
// 纵向连接原始字符串和框架化字符串
vector<string> col = vcat(v, fra);
// 横向连接原始字符串和框架化字符串
vector<string> row = hcat(v, fra);
// 输出横向连接后的结果
for (vector<string>::size_type j = 0; j != row.size(); ++j) {
cout << row[j] << endl;
}
}
return 0;
}

48
Chapter 6/6.9.cpp Normal file
View File

@ -0,0 +1,48 @@
#include <iostream>
#include <vector> //动态数组
#include <numeric>
#include <string>
using std::cin;
using std::endl;
using std::cout;
using std::vector;
using std::accumulate; //accumulate()函数返回数组内元素的累积值
using std::string;
int main(int argc, const char* argv[]) {
vector<string> v = { "zhang", "meng", "nan" , "1220310013"};
string str; //创建空字符串
str = accumulate(v.begin(), v.end(), str); //将v中所有字符加入str中
cout << str;
return 0;
}
#include <iostream> // 引入标准输入输出流库
#include <vector> // 引入动态数组vector容器库
#include <numeric> // 引入numeric库提供accumulate函数
#include <string> // 引入字符串库
using std::cin;
using std::endl;
using std::cout;
using std::vector;
using std::accumulate; // 引入accumulate函数用于累加容器内的元素
using std::string;
int main(int argc, const char* argv[]) {
// 初始化一个包含字符串的向量
vector<string> v = { "zhang", "meng", "nan", "1220310013" };
string str; // 创建一个空字符串,用于存储累积的结果
// 使用accumulate函数将vector v中的所有字符串连接起来
// accumulate的第三个参数是累积的初始值空字符串str用于开始累积
str = accumulate(v.begin(), v.end(), str);
// 输出累积后的字符串
cout << str; // 输出:"zhangmengnan1220310013"
return 0; // 程序结束
}

148
Chapter 7/7-3/7-3xref.cpp Normal file
View File

@ -0,0 +1,148 @@
#include <map>
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include "split.h"
using std::cin; using std::cout;
using std::endl; using std::getline;
using std::istream; using std::string;
using std::vector; using std::map;
using std::set;
// find all the lines that refer to each word in the input
map<string, set<int> >
xref(istream& in,
vector<string> find_words(const string&) = split)
{
string line;
int line_number = 0;
map<string, set<int> > ret;
// read the next line
while (getline(in, line)) {
++line_number;
// break the input line into words
vector<string> words = find_words(line);
// remember that each word occurs on the current line
#ifdef _MSC_VER
for (std::vector<string>::const_iterator it = words.begin();
#else
for (vector<string>::const_iterator it = words.begin();
#endif
it != words.end(); ++it)
ret[*it].insert(line_number);
}
return ret;
}
int main()
{
// call `xref' using `split' by default
map<string, set<int> > ret = xref(cin);
// write the results
#ifdef _MSC_VER
for (std::map<string, set<int> >::const_iterator it = ret.begin();
#else
for (map<string, set<int> >::const_iterator it = ret.begin();
#endif
it != ret.end(); ++it) {
// write the word
cout << it->first << " occurs on line(s): ";
// followed by one or more line numbers
#ifdef _MSC_VER
std::set<int>::const_iterator line_it = it->second.begin();
#else
set<int>::const_iterator line_it = it->second.begin();
#endif
cout << *line_it; // write the first line number
++line_it;
// write the rest of the line numbers, if any
while (line_it != it->second.end()) {
cout << ", " << *line_it;
++line_it;
}
// write a new line to separate each word from the next
cout << endl;
}
return 0;
}
#include <map> // 引入映射容器库map用于存储每个单词与其出现行数的对应关系
#include <iostream> // 引入标准输入输出流库
#include <string> // 引入字符串库
#include <vector> // 引入动态数组vector容器库
#include <set> // 引入集合容器库set用于存储行号
#include "split.h" // 引入自定义头文件split.h包含split函数的声明
using std::cin; // 引入标准输入流
using std::cout; // 引入标准输出流
using std::endl; // 引入换行符
using std::getline; // 引入getline函数用于逐行读取输入
using std::istream; // 引入输入流类
using std::string; // 引入字符串类
using std::vector; // 引入动态数组类
using std::map; // 引入映射容器类
using std::set; // 引入集合容器类
// xref 函数:查找每个单词在输入中出现的行号
map<string, set<int> >
xref(istream& in, // 输入流默认为cin
vector<string> find_words(const string&) = split) // 使用split函数分割单词默认
{
string line; // 用于存储每行的文本
int line_number = 0; // 当前行号
map<string, set<int>> ret; // 存储单词及其出现的行号使用map<单词, set<行号>>结构
// 逐行读取输入
while (getline(in, line)) {
++line_number; // 行号自增
// 将当前行拆分为单词使用find_words函数默认是split
vector<string> words = find_words(line);
// 遍历当前行中的每个单词将其对应的行号插入到map中
for (vector<string>::const_iterator it = words.begin(); it != words.end(); ++it)
ret[*it].insert(line_number); // 将单词及其行号存入map
}
return ret; // 返回map包含每个单词及其出现的行号
}
int main()
{
// 调用xref函数默认使用split函数进行单词拆分输入来自cin
map<string, set<int>> ret = xref(cin);
// 输出结果:每个单词及其出现的行号
for (map<string, set<int>>::const_iterator it = ret.begin(); it != ret.end(); ++it) {
// 输出单词
cout << it->first << " occurs on line(s): ";
// 输出该单词出现的所有行号
set<int>::const_iterator line_it = it->second.begin();
cout << *line_it; // 输出第一个行号
++line_it;
// 输出其余行号
while (line_it != it->second.end()) {
cout << ", " << *line_it;
++line_it;
}
// 输出换行符,以分隔每个单词的输出
cout << endl;
}
return 0; // 程序结束
}

43
Chapter 7/7-3/split.cpp Normal file
View File

@ -0,0 +1,43 @@
#include <cctype>
#include <string>
#include <vector>
#include "split.h"
using std::vector;
using std::string;
#ifndef _MSC_VER
using std::isspace;
#endif
vector<string> split(const string& s)
{
vector<string> ret;
typedef string::size_type string_size;
string_size i = 0;
// invariant: we have processed characters `['original value of `i', `i)'
while (i != s.size()) {
// ignore leading blanks
// invariant: characters in range `['original `i', current `i)' are all spaces
while (i != s.size() && isspace(s[i]))
++i;
// find end of next word
string_size j = i;
// invariant: none of the characters in range `['original `j', current `j)' is a space
while (j != s.size() && !isspace(s[j]))
++j;
// if we found some nonwhitespace characters
if (i != j) {
// copy from `s' starting at `i' and taking `j' `\-' `i' chars
ret.push_back(s.substr(i, j - i));
i = j;
}
}
return ret;
}

8
Chapter 7/7-3/split.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef GUARD_split_h
#define GUARD_split_h
#include <vector>
#include <string>
std::vector<std::string> split(const std::string&);
#endif

View File

@ -0,0 +1,251 @@
#ifdef _MSC_VER
#pragma warning(disable:4503) // `silence compiler complaints about generated names being too long'
#endif
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <map>
#include <stdexcept>
#include <string>
#include <vector>
#include "split.h"
#include <time.h>
using std::istream; using std::cin;
using std::copy; using std::cout;
using std::endl; using std::find;
using std::getline; using std::logic_error;
using std::map; using std::string;
using std::vector; using std::domain_error;
using std::rand;
typedef vector<string> Rule;
typedef vector<Rule> Rule_collection;
typedef map<string, Rule_collection> Grammar;
// read a grammar from a given input stream
Grammar read_grammar(istream& in)
{
Grammar ret;
string line;
// read the input
while (getline(in, line)) {
// `split' the input into words
vector<string> entry = split(line);
if (!entry.empty())
// use the category to store the associated rule
ret[entry[0]].push_back(
Rule(entry.begin() + 1, entry.end()));
}
return ret;
}
void gen_aux(const Grammar&, const string&, vector<string>&);
int nrand(int);
vector<string> gen_sentence(const Grammar& g)
{
vector<string> ret;
gen_aux(g, "<sentence>", ret);
return ret;
}
bool bracketed(const string& s)
{
return s.size() > 1 && s[0] == '<' && s[s.size() - 1] == '>';
}
void
gen_aux(const Grammar& g, const string& word, vector<string>& ret)
{
if (!bracketed(word)) {
ret.push_back(word);
} else {
// locate the rule that corresponds to `word'
Grammar::const_iterator it = g.find(word);
if (it == g.end())
throw logic_error("empty rule");
// fetch the set of possible rules
const Rule_collection& c = it->second;
// from which we select one at random
const Rule& r = c[nrand(c.size())];
// recursively expand the selected rule
for (Rule::const_iterator i = r.begin(); i != r.end(); ++i)
gen_aux(g, *i, ret);
}
}
int main()
{
// generate the sentence
vector<string> sentence = gen_sentence(read_grammar(cin));
// write the first word, if any
#ifdef _MSC_VER
std::vector<string>::const_iterator it = sentence.begin();
#else
vector<string>::const_iterator it = sentence.begin();
#endif
if (!sentence.empty()) {
cout << *it;
++it;
}
// write the rest of the words, each preceded by a space
while (it != sentence.end()) {
cout << " " << *it;
++it;
}
cout << endl;
return 0;
}
// return a random integer in the range `[0,' `n)'
int nrand(int n)
{
if (n <= 0 || n > RAND_MAX)
throw domain_error("Argument to nrand is out of range");
const int bucket_size = RAND_MAX / n;
int r;
do r = rand() / bucket_size;
while (r >= n);
return r;
}
#ifdef _MSC_VER
#pragma warning(disable:4503) // 关闭编译器警告,避免对生成的名称过长的抱怨
#endif
#include <algorithm> // 引入算法库,提供常用的算法
#include <cstdlib> // 引入C标准库包含rand()函数
#include <iostream> // 引入标准输入输出流库
#include <map> // 引入映射容器map
#include <stdexcept> // 引入标准异常库,提供逻辑错误和域错误等异常
#include <string> // 引入字符串库
#include <vector> // 引入动态数组vector
#include "split.h" // 引入自定义的split.h头文件假定提供了字符串拆分功能
#include <time.h> // 引入时间库,支持随机数生成
using std::istream; using std::cin;
using std::copy; using std::cout;
using std::endl; using std::find;
using std::getline; using std::logic_error;
using std::map; using std::string;
using std::vector; using std::domain_error;
using std::rand; // 引入rand函数
// 定义规则(字符串集合)和语法(规则集合)的类型
typedef vector<string> Rule; // 一个规则是字符串的集合
typedef vector<Rule> Rule_collection; // 规则集合是规则的集合
typedef map<string, Rule_collection> Grammar; // 语法是一个映射:类别 -> 规则集合
// 从输入流中读取语法并返回
Grammar read_grammar(istream& in) {
Grammar ret; // 用于存储语法
string line;
// 持续读取每一行
while (getline(in, line)) {
// 将当前行拆分成单词
vector<string> entry = split(line);
// 如果拆分出的单词不为空,则根据类别存储规则
if (!entry.empty())
ret[entry[0]].push_back(
Rule(entry.begin() + 1, entry.end())); // 使用类别作为key规则作为value
}
return ret; // 返回语法
}
// 递归生成句子的辅助函数
void gen_aux(const Grammar&, const string&, vector<string>&);
// 返回一个范围在[0, n)内的随机整数
int nrand(int);
// 生成一个句子调用gen_aux进行递归生成
vector<string> gen_sentence(const Grammar& g) {
vector<string> ret;
gen_aux(g, "<sentence>", ret); // 从<sentence>开始生成句子
return ret;
}
// 判断一个字符串是否是被尖括号包围的
bool bracketed(const string& s) {
return s.size() > 1 && s[0] == '<' && s[s.size() - 1] == '>';
}
// 递归地生成句子中的一部分
void gen_aux(const Grammar& g, const string& word, vector<string>& ret) {
if (!bracketed(word)) {
ret.push_back(word); // 如果不是被尖括号包围的单词,直接加入句子
}
else {
// 查找对应的规则
Grammar::const_iterator it = g.find(word);
if (it == g.end()) // 如果没有找到规则,抛出异常
throw logic_error("empty rule");
// 获取该单词的规则集合
const Rule_collection& c = it->second;
// 从规则集合中随机选择一个规则
const Rule& r = c[nrand(c.size())];
// 对选中的规则中的每个单词进行递归处理
for (Rule::const_iterator i = r.begin(); i != r.end(); ++i)
gen_aux(g, *i, ret);
}
}
int main() {
// 生成句子
vector<string> sentence = gen_sentence(read_grammar(cin));
// 输出第一个单词(如果有)
vector<string>::const_iterator it = sentence.begin();
if (!sentence.empty()) {
cout << *it;
++it;
}
// 输出剩余的单词,每个单词前加一个空格
while (it != sentence.end()) {
cout << " " << *it;
++it;
}
cout << endl; // 输出换行
return 0;
}
// 返回一个随机整数,范围在[0, n)
int nrand(int n) {
if (n <= 0 || n > RAND_MAX)
throw domain_error("Argument to nrand is out of range");
const int bucket_size = RAND_MAX / n; // 将随机数均匀分布
int r;
// 确保随机数在有效范围内
do r = rand() / bucket_size;
while (r >= n);
return r;
}

View File

@ -0,0 +1,43 @@
#include <cctype>
#include <string>
#include <vector>
#include "split.h"
using std::vector;
using std::string;
#ifndef _MSC_VER
using std::isspace;
#endif
vector<string> split(const string& s)
{
vector<string> ret;
typedef string::size_type string_size;
string_size i = 0;
// invariant: we have processed characters `['original value of `i', `i)'
while (i != s.size()) {
// ignore leading blanks
// invariant: characters in range `['original `i', current `i)' are all spaces
while (i != s.size() && isspace(s[i]))
++i;
// find end of next word
string_size j = i;
// invariant: none of the characters in range `['original `j', current `j)' is a space
while (j != s.size() && !isspace(s[j]))
++j;
// if we found some nonwhitespace characters
if (i != j) {
// copy from `s' starting at `i' and taking `j' `\-' `i' chars
ret.push_back(s.substr(i, j - i));
i = j;
}
}
return ret;
}

View File

@ -0,0 +1,8 @@
#ifndef GUARD_split_h
#define GUARD_split_h
#include <vector>
#include <string>
std::vector<std::string> split(const std::string&);
#endif

View File

@ -0,0 +1,108 @@
#include <algorithm>
#include <string>
#include <vector>
#include "pics.h"
using std::string;
using std::vector;
using std::max;
#ifdef _MSC_VER
//#include "../minmax.h"
#else
//using std::max;
#endif
string::size_type width(const vector<string>& v)
{
string::size_type maxlen = 0;
#ifdef _MSC_VER
for(std::vector<string>::size_type i = 0; i != v.size(); ++i)
#else
for(vector<string>::size_type i = 0; i != v.size(); ++i)
#endif
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, '*');
// write the top border
ret.push_back(border);
// write each interior row, bordered by an asterisk and a space
#ifdef _MSC_VER
for (std::vector<string>::size_type i = 0; i != v.size(); ++i) {
#else
for (vector<string>::size_type i = 0; i != v.size(); ++i) {
#endif
ret.push_back("* " + v[i] +
string(maxlen - v[i].size(), ' ') + " *");
}
// write the bottom border
ret.push_back(border);
return ret;
}
vector<string> vcat(const vector<string>& top,
const vector<string>& bottom)
{
// copy the `top' picture
vector<string> ret = top;
// copy entire `bottom' picture
#ifdef _MSC_VER
for (std::vector<string>::const_iterator it = bottom.begin();
#else
for (vector<string>::const_iterator it = bottom.begin();
#endif
it != bottom.end(); ++it)
ret.push_back(*it);
return ret;
}
vector<string>
hcat(const vector<string>& left, const vector<string>& right)
{
vector<string> ret;
// add 1 to leave a space between pictures
string::size_type width1 = width(left) + 1;
// indices to look at elements from `left' and `right' respectively
#ifdef _MSC_VER
std::vector<string>::size_type i = 0, j = 0;
#else
vector<string>::size_type i = 0, j = 0;
#endif
string s;
// continue until we've seen all rows from both pictures
while (i != left.size() || j != right.size()) {
// construct new `string' to hold characters from both pictures
//string s;
// copy a row from the left-hand side, if there is one
if (i != left.size())
s = left[i++];
// pad to full width
s += string(width1 - s.size(), ' ');
// copy a row from the right-hand side, if there is one
if (j != right.size())
s += right[j++];
// add `s' to the picture we're creating
ret.push_back(s);
}
return ret;
}

View File

@ -0,0 +1,17 @@
#ifndef GUARD_pics_h
#define GUARD_pics_h
#include <string>
#include <vector>
std::string::size_type width(const std::vector<std::string>& v);
std::vector<std::string> frame(const std::vector<std::string>& v);
std::vector<std::string> vcat(const std::vector<std::string>& top,
const std::vector<std::string>& bottom);
std::vector<std::string> hcat(const std::vector<std::string>& left,
const std::vector<std::string>& right);
#endif

View File

@ -0,0 +1,85 @@
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
#include "pics.h"
using std::cout;
using std::copy;
using std::endl;
using std::ostream_iterator;
using std::string;
using std::vector;
int main()
{
vector<string> p;
p.push_back("this is an");
p.push_back("example");
p.push_back("to");
p.push_back("illustrate");
p.push_back("framing");
ostream_iterator<string>ofile(cout, "\n");
copy(p.begin(), p.end(), ofile);
cout << endl;
vector<string> f = frame(p);
copy(f.begin(), f.end(), ofile); cout << endl;
vector<string> h = hcat(p,frame(p));
copy(h.begin(), h.end(), ofile);
cout << endl;
return 0;
}
#include <algorithm> // 引入算法库,提供常用的算法
#include <iostream> // 引入标准输入输出流库
#include <iterator> // 引入迭代器库
#include <string> // 引入字符串库
#include <vector> // 引入动态数组vector
#include "pics.h" // 引入自定义的 pics.h 库(假设此库包含框架生成和拼接相关的功能)
using std::cout; // 使用标准输出流
using std::copy; // 引入copy算法
using std::endl; // 引入换行符
using std::ostream_iterator; // 引入输出流迭代器,用于输出容器的内容
using std::string; // 使用字符串类型
using std::vector; // 使用vector容器
int main() {
// 创建一个vector<string>类型的容器 p存储字符串
vector<string> p;
p.push_back("this is an"); // 添加一个字符串
p.push_back("example"); // 添加一个字符串
p.push_back("to"); // 添加一个字符串
p.push_back("illustrate"); // 添加一个字符串
p.push_back("framing"); // 添加一个字符串
// 创建输出流迭代器,指定输出到 cout并且每个元素输出后换行
ostream_iterator<string> ofile(cout, "\n");
// 使用copy算法将vector p中的内容逐个输出
copy(p.begin(), p.end(), ofile);
cout << endl; // 输出换行符
// 对vector p应用框架操作生成一个新的vector f
vector<string> f = frame(p);
// 使用copy算法将vector f中的内容逐个输出
copy(f.begin(), f.end(), ofile);
cout << endl; // 输出换行符
// 将vector p和vector f进行横向拼接生成一个新的vector h
vector<string> h = hcat(p, frame(p));
// 使用copy算法将vector h中的内容逐个输出
copy(h.begin(), h.end(), ofile);
cout << endl; // 输出换行符
return 0; // 程序正常结束
}

View File

@ -0,0 +1,145 @@
#include <map>
#include <iostream>
#include <string>
#include <vector>
#include "split.h"
using std::cin; using std::cout;
using std::endl; using std::getline;
using std::istream; using std::string;
using std::vector; using std::map;
// find all the lines that refer to each word in the input
map<string, vector<int> >
xref(istream& in,
vector<string> find_words(const string&) = split)
{
string line;
int line_number = 0;
map<string, vector<int> > ret;
// read the next line
while (getline(in, line)) {
++line_number;
// break the input line into words
vector<string> words = find_words(line);
// remember that each word occurs on the current line
#ifdef _MSC_VER
for (std::vector<string>::const_iterator it = words.begin();
#else
for (vector<string>::const_iterator it = words.begin();
#endif
it != words.end(); ++it)
ret[*it].push_back(line_number);
}
return ret;
}
int main()
{
// call `xref' using `split' by default
map<string, vector<int> > ret = xref(cin);
// write the results
#ifdef _MSC_VER
for (std::map<string, vector<int> >::const_iterator it = ret.begin();
#else
for (map<string, vector<int> >::const_iterator it = ret.begin();
#endif
it != ret.end(); ++it) {
// write the word
cout << it->first << " occurs on line(s): ";
// followed by one or more line numbers
#ifdef _MSC_VER
std::vector<int>::const_iterator line_it = it->second.begin();
#else
vector<int>::const_iterator line_it = it->second.begin();
#endif
cout << *line_it; // write the first line number
++line_it;
// write the rest of the line numbers, if any
while (line_it != it->second.end()) {
cout << ", " << *line_it;
++line_it;
}
// write a new line to separate each word from the next
cout << endl;
}
return 0;
}
#include <map> // 引入 map 容器,用于存储每个单词及其出现的行号
#include <iostream> // 引入标准输入输出流库
#include <string> // 引入字符串库
#include <vector> // 引入动态数组库,用于存储每一行的单词
#include "split.h" // 引入自定义的 split.h 库,假设包含用于分割字符串的函数
using std::cin; // 使用标准输入流
using std::cout; // 使用标准输出流
using std::endl; // 使用换行符
using std::getline; // 使用getline函数读取整行输入
using std::istream; // 使用输入流
using std::string; // 使用字符串类型
using std::vector; // 使用vector容器
using std::map; // 使用map容器
// xref函数用来查找每个单词在文本中出现的行号
// 参数:输入流 in 和一个函数指针 find_words用于分割每行的单词默认为 split 函数)
map<string, vector<int> >
xref(istream& in,
vector<string> find_words(const string&) = split)
{
string line; // 用来存储每一行的文本
int line_number = 0; // 行号
map<string, vector<int> > ret; // 用map来存储每个单词及其对应的行号
// 按行读取输入
while (getline(in, line)) {
++line_number; // 增加行号
// 调用find_words函数将一行文本分割成单词
vector<string> words = find_words(line);
// 将当前行号添加到每个单词的对应位置
for (vector<string>::const_iterator it = words.begin(); it != words.end(); ++it)
ret[*it].push_back(line_number); // 将单词和行号对应起来
}
return ret; // 返回包含每个单词及其行号的map
}
int main()
{
// 调用 xref 函数,默认使用 split 来分割单词
map<string, vector<int> > ret = xref(cin);
// 输出结果
for (map<string, vector<int> >::const_iterator it = ret.begin(); it != ret.end(); ++it) {
// 输出单词
cout << it->first << " occurs on line(s): ";
// 获取并输出单词出现的行号
vector<int>::const_iterator line_it = it->second.begin();
cout << *line_it; // 输出第一个行号
++line_it;
// 输出其余的行号
while (line_it != it->second.end()) {
cout << ", " << *line_it;
++line_it;
}
// 换行
cout << endl;
}
return 0; // 程序结束
}

View File

@ -0,0 +1,43 @@
#include <cctype>
#include <string>
#include <vector>
#include "split.h"
using std::vector;
using std::string;
#ifndef _MSC_VER
using std::isspace;
#endif
vector<string> split(const string& s)
{
vector<string> ret;
typedef string::size_type string_size;
string_size i = 0;
// invariant: we have processed characters `['original value of `i', `i)'
while (i != s.size()) {
// ignore leading blanks
// invariant: characters in range `['original `i', current `i)' are all spaces
while (i != s.size() && isspace(s[i]))
++i;
// find end of next word
string_size j = i;
// invariant: none of the characters in range `['original `j', current `j)' is a space
while (j != s.size() && !isspace(s[j]))
++j;
// if we found some nonwhitespace characters
if (i != j) {
// copy from `s' starting at `i' and taking `j' `\-' `i' chars
ret.push_back(s.substr(i, j - i));
i = j;
}
}
return ret;
}

View File

@ -0,0 +1,8 @@
#ifndef GUARD_split_h
#define GUARD_split_h
#include <vector>
#include <string>
std::vector<std::string> split(const std::string&);
#endif

View File

@ -0,0 +1,45 @@
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include "split.h"
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
// 函数:反转字符串
string reverseString(const string& s) {
return string(s.rbegin(), s.rend());
}
int main() {
// 读取输入文本
cout << "输入一段文本: ";
string input;
std::getline(cin, input);
// 拆分文本为单词
vector<string> words = split(input);
// 对每个单词进行反转
for (auto& word : words) {
word = reverseString(word);
}
// 按照反转后的单词排序
std::sort(words.begin(), words.end());
// 输出排序后的单词,保持与原输入格式一致
for (size_t i = 0; i < words.size(); ++i) {
if (i > 0) {
cout << " "; // 单词间加空格
}
cout << words[i];
}
cout << endl;
return 0;
}

View File

@ -0,0 +1,43 @@
#include <cctype>
#include <string>
#include <vector>
#include "split.h"
using std::vector;
using std::string;
#ifndef _MSC_VER
using std::isspace;
#endif
vector<string> split(const string& s)
{
vector<string> ret;
typedef string::size_type string_size;
string_size i = 0;
// invariant: we have processed characters `['original value of `i', `i)'
while (i != s.size()) {
// ignore leading blanks
// invariant: characters in range `['original `i', current `i)' are all spaces
while (i != s.size() && isspace(s[i]))
++i;
// find end of next word
string_size j = i;
// invariant: none of the characters in range `['original `j', current `j)' is a space
while (j != s.size() && !isspace(s[j]))
++j;
// if we found some nonwhitespace characters
if (i != j) {
// copy from `s' starting at `i' and taking `j' `\-' `i' chars
ret.push_back(s.substr(i, j - i));
i = j;
}
}
return ret;
}

View File

@ -0,0 +1,8 @@
#ifndef GUARD_split_h
#define GUARD_split_h
#include <vector>
#include <string>
std::vector<std::string> split(const std::string&);
#endif

View File

@ -0,0 +1,41 @@
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include "urls.h"
using std::cin;
using std::cout;
using std::endl;
using std::sort;
using std::string;
using std::vector;
int main() {
// 输入文本
cout << "输入一段文本: ";
string input;
std::getline(cin, input);
// 提取所有 URL
vector<string> urls = find_urls(input);
// 筛选出以 http:// 或 https:// 开头的 URL
vector<string> http_urls;
for (const string& url : urls) {
if (url.find("http://") == 0 || url.find("https://") == 0) {
http_urls.push_back(url);
}
}
// 按字母顺序排序
sort(http_urls.begin(), http_urls.end());
// 输出结果
cout << "排序后的 HTTP URLs:" << endl;
for (const string& url : http_urls) {
cout << url << endl;
}
return 0;
}

View File

@ -0,0 +1,101 @@
#include <algorithm>
#include <cctype>
#include <string>
#include <vector>
#include "urls.h"
using std::find;
using std::find_if;
#ifndef _MSC_VER
using std::isalnum;
using std::isalpha;
using std::isdigit;
#endif
using std::search;
using std::string;
using std::vector;
bool not_url_char(char);
string::const_iterator
url_end(string::const_iterator, string::const_iterator);
string::const_iterator
url_beg(string::const_iterator, string::const_iterator);
vector<string> find_urls(const string& s)
{
vector<string> ret;
typedef string::const_iterator iter;
iter b = s.begin(), e = s.end();
// look through the entire input
while (b != e) {
// look for one or more letters followed by `://'
b = url_beg(b, e);
// if we found it
if (b != e) {
// get the rest of the \s-1URL\s0
iter after = url_end(b, e);
// remember the \s-1URL\s0
ret.push_back(string(b, after));
// advance `b' and check for more \s-1URL\s0s on this line
b = after;
}
}
return ret;
}
string::const_iterator
url_end(string::const_iterator b, string::const_iterator e)
{
return find_if(b, e, not_url_char);
}
bool not_url_char(char c)
{
// characters, in addition to alphanumerics, that can appear in a \s-1URL\s0
static const string url_ch = "~;/?:@=&$-_.+!*'(),";
// see whether `c' can appear in a \s-1URL\s0 and return the negative
return !(isalnum(c) ||
find(url_ch.begin(), url_ch.end(), c) != url_ch.end());
}
string::const_iterator
url_beg(string::const_iterator b, string::const_iterator e)
{
static const string sep = "://";
typedef string::const_iterator iter;
// `i' marks where the separator was found
iter i = b;
while ((i = search(i, e, sep.begin(), sep.end())) != e) {
// make sure the separator isn't at the beginning or end of the line
if (i != b && i + sep.size() != e) {
// `beg' marks the beginning of the protocol-name
iter beg = i;
while (beg != b && isalpha(beg[-1]))
--beg;
// is there at least one appropriate character before and after the separator?
if (beg != i && !not_url_char(i[sep.size()]))
return beg;
}
// the separator we found wasn't part of a \s-1URL\s0; advance `i' past this separator
i += sep.size();
}
return e;
}

View File

@ -0,0 +1,9 @@
#ifndef GUARD_urls_h
#define GUARD_urls_h
#include <vector>
#include <string>
std::vector<std::string> find_urls(const std::string& s);
#endif

View File

@ -0,0 +1,37 @@
// source file for `Student_info'-related functions
#include "Student_info.h"
using std::istream; using std::vector;
bool compare(const Student_info& x, const Student_info& y)
{
return x.name < y.name;
}
istream& read(istream& is, Student_info& s)
{
// read and store the student's name and midterm and final exam grades
is >> s.name >> s.midterm >> s.final;
read_hw(is, s.homework); // read and store all the student's homework grades
return is;
}
// read homework grades from an input stream into a `vector<double>'
istream& read_hw(istream& in, vector<double>& hw)
{
if (in) {
// get rid of previous contents
hw.clear();
// read homework grades
double x;
while (in >> x)
hw.push_back(x);
// clear the stream so that input will work for the next student
in.clear();
}
return in;
}

View File

@ -0,0 +1,19 @@
#ifndef GUARD_Student_info
#define GUARD_Student_info
// `Student_info.h' header file
#include <iostream>
#include <string>
#include <vector>
struct Student_info {
std::string name;
double midterm, final;
std::vector<double> homework;
};
bool compare(const Student_info&, const Student_info&);
std::istream& read(std::istream&, Student_info&);
std::istream& read_hw(std::istream&, std::vector<double>&);
#endif

View File

@ -0,0 +1,41 @@
#include <stdexcept>
#include <vector>
#include "grade.h"
#include "median.h"
#include "Student_info.h"
using std::domain_error; using std::vector;
// compute a student's overall grade from midterm and final exam grades and homework grade
double grade(double midterm, double final, double homework)
{
return 0.2 * midterm + 0.4 * final + 0.4 * homework;
}
// compute a student's overall grade from midterm and final exam grades
// and vector of homework grades.
// this function does not copy its argument, because `median' does so for us.
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));
}
double grade(const Student_info& s)
{
return grade(s.midterm, s.final, s.homework);
}
// predicate to determine whether a student failed
bool fgrade(const Student_info& s)
{
return grade(s) < 60;
}
bool pgrade(const Student_info& s)
{
return !fgrade(s);
}

View File

@ -0,0 +1,14 @@
#ifndef GUARD_grade_h
#define GUARD_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&);
bool pgrade(const Student_info&);
bool fgrade(const Student_info&);
#endif

View File

@ -0,0 +1,57 @@
#include <iostream>
#include <vector>
#include <algorithm>
#include "Student_info.h"
#include "grade.h"
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
// 定义常量:及格分数
const double PASS_GRADE = 60.0;
int main() {
vector<Student_info> students;
Student_info record;
// 读取学生信息
cout << "期中成绩占比20%、期末成绩占比40%平时成绩占比40%:" << endl;
cout << "输入学生信息(姓名、期中成绩、期末成绩,平时成绩):" << endl;
cout << "输入Ctrl+z后回车退出。" << endl;
while (read(cin, record)) {
students.push_back(record);
}
// 将学生分为及格和不及格两组
vector<Student_info> pass, fail;
for (const auto& student : students) {
if (grade(student) >= PASS_GRADE) {
pass.push_back(student);
}
else {
fail.push_back(student);
}
}
// 按名字排序
std::sort(pass.begin(), pass.end(), compare);
std::sort(fail.begin(), fail.end(), compare);
// 输出及格学生信息
cout << "合格学生:" << endl;
for (const auto& student : pass) {
cout << student.name << ": 总成绩 = " << grade(student) << endl;
}
// 输出不及格学生信息
cout << "不合格学生:" << endl;
for (const auto& student : fail) {
cout << student.name << ": 总成绩 = " << grade(student) << endl;
}
return 0;
}

View File

@ -0,0 +1,30 @@
// source file for the `median' function
#include <algorithm> // to get the declaration of `sort'
#include <stdexcept> // to get the declaration of `domain_error'
#include <vector> // to get the declaration of `vector'
using std::domain_error; using std::sort; using std::vector;
#include "median.h"
// compute the median of a `vector<double>'
// note that calling this function copies the entire argument `vector'
double median(vector<double> vec)
{
#ifdef _MSC_VER
typedef std::vector<double>::size_type vec_sz;
#else
typedef vector<double>::size_type vec_sz;
#endif
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];
}

View File

@ -0,0 +1,9 @@
#ifndef GUARD_median_h
#define GUARD_median_h
// `median.h'--final version
#include <vector>
double median(std::vector<double>);
#endif