第3章 使用批量数据
<span style="font-family:KaiTi_GB2312;">// lesson3_1.cpp : 定义控制台应用程序的入口点。
//功能:假设有一门课程中,每一个学生的总成绩都由期末考试成绩(40%),期中考试成绩(20%)和家庭作业的平均成绩(40%)构成。
//时间:2014.5.8
#include "stdafx.h"
#include "iomanip"
#include "ios"
#include "iostream"
#include "string"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
//请求输入并读入学生的姓名
cout << "Please enter your first name: ";
string name;
cin >> name;
cout << "Hello, " << name << "!" << endl;
//请求输入并读入期中和期末考试成绩
cout << "Please enter your midterm and final exam grades: ";
double midterm, final;
cin >> midterm >> final;
//请求输入家庭作业成绩
cout << "Enter all your homework grades, "
"followed by end-of-file: ";
//到目前为止,读入的家庭作业成绩的个数及总和
int count = 0;
double sum = 0;
//把家庭作业的成绩读到变量x中
double x;
//不变式:
//到目前为止,我们已经读到了count个家庭作业成绩,
//而且sum等于头count个成绩的总和
while (cin >> x)
{
++count;
sum += x;
}
//输出结果
streamsize prec = cout.precision();
cout << "Your final grade is " << setprecision(3)
<< 0.2 * midterm + 0.4 * final + 0.4 * sum/count
<< setprecision(prec) << endl;
return 0;
}
</span>
运行结果:
<span style="font-family:KaiTi_GB2312;"> //请求输入家庭作业成绩
cout << "Enter all your homework grades, "
"followed by end-of-file: ";</span>
4)检测输入
<span style="font-family:KaiTi_GB2312;">while(cin >> x){……}
if(cin >> x){}//请求cin>>x的值等价于先执行cin>>x之后请求cin的值</span>
2、如果计算总成绩的时候用中值代替平均值呢?
<span style="font-family:KaiTi_GB2312;">// lesson3_2.cpp : 定义控制台应用程序的入口点。
//功能:假设有一门课程中,每一个学生的总成绩都由期末考试成绩(40%),期中考试成绩(20%)和家庭作业的中值成绩(40%)构成。
//时间:2014.5.8
#include "stdafx.h"
#include "algorithm"
#include "iomanip"
#include "ios"
#include "iostream"
#include "string"
#include "vector"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
//请求输入并读出学生的姓名
cout << "Please enter your first name: ";
string name;
cin >> name;
cout << "Hello, " << name << "!" << endl;
//请求输入并读入期中和期末成绩
cout << "Please enter your midterm and final exam grades: ";
double midterm, final;
cin >> midterm >> final;
//请求输入家庭作业成绩
cout << "Enter all your homework grades, "
"followed by end-of-file: ";
vector<double> homework;
double x;
//不变式:homework包含了所有的家庭作业成绩
while (cin >> x)
homework.push_back(x);
//检查homework是否为空
typedef vector<double>::size_type vec_sz;
vec_sz size = homework.size();
if (size == 0)
{
cout << endl << "You must enter your grades. "
<< "Please try again." << endl;
return 1;
}
//对成绩进行排序
sort(homework.begin(), homework.end());
//计算家庭作业成绩的中值
vec_sz mid = size/2;
double median;
median = (size % 2 == 0) ? (homework[mid] + homework[mid - 1]) / 2 : homework[mid];
//计算并输出总成绩
streamsize prec = cout.precision();
cout << "Your final grade is " << setprecision(3)
<< 0.2 * midterm + 0.4 * final + 0.4 * median
<< setprecision(prec) << endl;
return 0;
}
</span>
运行结果:
<span style="font-family:KaiTi_GB2312;">// lesson3_3.cpp : 定义控制台应用程序的入口点。
//功能:把一个整数集合分为个数相等的四部分,而且第一部分含有的整数值比其他各部分的都大,第二部分的值比第一部分小,但是比其他部分都大
//时间:2014.5.8
#include "stdafx.h"
#include "algorithm"
#include "iostream"
#include "vector"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
//请求输入并读入一个整数集合
cout << "Please enter the integer: ";
vector<int> integer;
int x;
//不变式:integer包含了所有的家庭作业成绩
while (cin >> x)
integer.push_back(x);
//检查integer是否为空
typedef vector<int>::size_type vec_sz;
vec_sz size = integer.size();
if (size == 0)
{
cout << "It is not integer!" << endl;
return 1;
}
//对这些数进行排序
sort(integer.begin(),integer.end());
vec_sz size_avg = size/4;
//输出四部分
cout << "The first part: " << endl;
for(vec_sz i = 0;i <= (size_avg - 1) ; i++)
{
cout << integer[i] << endl;
}
cout << "The second part: " << endl;
for(vec_sz i = size_avg;i <= (2*size_avg - 1) ; i++)
{
cout << integer[i] << endl;
}
cout << "The third part: " << endl;
for(vec_sz i = 2*size_avg;i <= (3*size_avg - 1) ; i++)
{
cout << integer[i] << endl;
}
cout << "The fourth part: " << endl;
for(vec_sz i = 3*size_avg;i <= (4*size_avg - 1) ; i++)
{
cout << integer[i] << endl;
}
return 0;
}
</span>
运行结果:
<span style="font-family:KaiTi_GB2312;">// lesson3_4.cpp : 定义控制台应用程序的入口点。
//功能:编写一个程序来计算在它的输入中每一个不同的单词所出现的次数
//时间:2014.5.8
#include "stdafx.h"
#include "iostream"
#include "string"
#include "vector"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
//请求输入并读入单词
cout << "Please enter words: ";
vector<string> words;
vector<int> counts;
string x;
typedef vector<string>::size_type vec_sz;
//不变式:words包含所有的不同的单词
while (cin >> x)
{
bool found = false;
for(vec_sz i = 0; i < words.size(); ++i)
{
if(x == words[i])
{
++counts[i];
found = true;
}
}
if (!found)
{
words.push_back(x);
counts.push_back(1);
}
}
for(vec_sz i = 0; i < words.size(); ++i)
cout << words[i] << " appeared " << counts[i] << " times" << endl;
return 0;
}
</span>
运行程序:
<span style="font-family:KaiTi_GB2312;">// lesson3_5.cpp : 定义控制台应用程序的入口点。
//功能:编写一个程序来报告它的输入中最长以及最短的字符串的长度
//2014.5.8
#include "stdafx.h"
#include "iostream"
#include "string"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
typedef string::size_type str_sz;
string longest;
str_sz longest_length = 0;
string shortest;
str_sz shortest_length = 0;
//请求输入字符串
cout << "Please enter character: ";
string s;
//不变式
while (cin >> s)
{
if(longest_length == 0 || s.size() > longest_length)
{
longest = s;
longest_length = s.size();
}
if(shortest_length == 0 || s.size() < shortest_length)
{
shortest = s;
shortest_length = s.size();
}
}
cout << "Longest: " << longest << longest_length << endl;
cout << "Shortest: " << shortest << shortest_length << endl;
return 0;
}
</span>
运行结果:
<span style="font-family:KaiTi_GB2312;">// lesson3_6.cpp : 定义控制台应用程序的入口点。
//功能:编写一个程序来同时跟踪n个学生的成绩,要求程序能够保持两个向量的同步:第一个应保存学生的姓名;第二个保存总成绩 这个其实和lesson3_1一样的
//时间:2014.5.8
#include "stdafx.h"
#include "iomanip"
#include "ios"
#include "iostream"
#include "string"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
//请求输入并读入学生的姓名
cout << "Please enter your first name: ";
string name;
cin >> name;
cout << "Hello, " << name << "!" << endl;
//请求输入并读入期中和期末考试成绩
cout << "Please enter your midterm and final exam grades: ";
double midterm, final;
cin >> midterm >> final;
//请求输入家庭作业成绩
cout << "Enter all your homework grades, "
"followed by end-of-file: ";
//到目前为止,读入的家庭作业成绩的个数及总和
int count = 0;
double sum = 0;
//把家庭作业的成绩读到变量x中
double x;
//不变式:
//到目前为止,我们已经读到了count个家庭作业成绩,
//而且sum等于头count个成绩的总和
while (cin >> x)
{
++count;
sum += x;
}
double homework_grade = (count > 0) ? sum / count : 0.0;
//输出结果
streamsize prec = cout.precision();
cout << "Your final grade is " << setprecision(3)
<< 0.2 * midterm + 0.4 * final + 0.4 * homework_grade
<< setprecision(prec) << endl;
return 0;
}
</span>
运行结果:
证明:在已经读了N个值后,我们丢弃了一个值x。可以计算出,在已读集合中,比x大的值有n1个,比x小的值有n2个,n1+n2 < N(注意n1+n2不一定等于N-1,因为可能存在于x相等的值)。
1) 首先考虑在已读集合中,x只有一个,那么令d = max(n1,n2) - min(n1,n2)。再令集合s = { n1 > n2 ? d个(x-1) : d个(x+1) },s就是使的x成为整个集合中值的后续数值集合,从而x不能丢弃。
2) 在考虑x有多个的情况,设为n3个,此时n1+n2+n3 = N,并令y1为输入值中比x大的所有值中最小的一个(即大于x的子集的下确界),类似,令y2为小于x的子集的上确界。
令d= max(n1,n2) - min(n1,n2)。令集合s = { n1 > n2 ? d个y2 : d个y1 }
再令 y3 = (x-y2)/2,令集合s\' = {(n3-1)个 y3 }。s并s\'即是令x为中值的后续数值集合。因为当整个集合中有n3个x时,中值是x,如果去掉一个x,则要根据中值在此时的定义决定:
a)如果整个集合为偶数时,取中间偏小的那个为中值,那么去掉x后,y3就成为中值,这是错误的,说明x不能去除。
b)如果整个集合为偶数时,取中间偏大的那个为中值,可以令y3\' = (y1-x)/2代替上面的y3,则y3\'就是新的中值。这是错误的,同样说明x不能去除。
综上,在任何情况下去除输入数值中的任何一个,都有可能(即存在一个未输入数值集合)使得整个集合的中值发生改变。
8、小结:本节主要讲解了如何处理批量数据,还有如何计算中值,这一节中一些常用的语句用法需要大家多多熟练。