2021.10.25 想了想还是重新编辑一下,每一个大章节写一篇记录好了。
1.第三章的实例程序
第三章的程序主要是要实现一个自动计算学生总成绩的小程序。难点重点在于使用while循环计算平均值和使用vector 向量存储多个数值并且用成员函数vector<>::size_type得知长度来寻找中值的位置。
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<ios>
#include<iomanip>
using namespace std;
int main()
{
cout << "请输入你的姓名" << endl;
string name;
cin >> name;
cout << "请输入你的期中、期末成绩" << endl;
double midterm, endterm;
cin >> midterm >> endterm;
cout << "请输入你的作业成绩" << endl;
//因为要取作业成绩的中值,就需要储存每一个输入的作业成绩。使用vector来做这件事。
vector<double> homework;
double x;
while (cin >> x && x != 101)//输入101,则循环结束
homework.push_back(x);//读入x,并将x置于容器homework的末尾
//为了防止程序报错,在这里增加一个检测homework总长度的环节
typedef vector<double>::size_type vcsize;//将vcsize定义为vector<double>;;size_type这个类型的替代名
vcsize size = homework.size();//定义size为计量homework这一容器长度的变量。类型是vector类型以表示长度的成员函数vector<double>;;size_type
if (size == 0) {
cout << "请输入你的平时作业成绩,再试一次吧" << endl;
return 1;//返回1表示程序终止。
}
//要开始确定homework中一系列数的中值
sort(homework.begin(), homework.end());//从homework的第一个到最后一个数进行非递减排列
vcsize mid = size / 2;
double middle = 0;//因为报错:不能使用未初始化的变量,因此要对middle进行初始化
if (size % 2 == 0)
middle += (homework[mid] + homework[mid - 1]) / 2;//因为要改变middle的值,所以不能用double middle,用+=改变middle的值。
else
middle += homework[mid];
cout << "你的作业成绩的中值是:"<<middle << endl;
//输出最后的总成绩
streamsize prec = cout.precision();
cout << "你的最终成绩是" << setprecision(3) << 0.4*midterm + 0.4*endterm + 0.2*middle << "。" << setprecision(prec) << endl;
return 0;
}
(1).若要计算作业成绩的平均值,只需要如下:
double sum=0;
int count=0;
double x;
while(cin>>x&&x!=101){
sum+=x;
count++}//当x输入101时跳出循环。作业成绩的平均值为sum/count.
(2).计算中值时,使用的向量函数vector
vector<double> homework,意为创建一个名为homework的向量,用来存储double类型的数值。
homework.push_back(x)意为将x加进这个容器的末位。
typedef a b,意为用名称b替代名称a。因为代码中vector<double>::type_size太长了,所以用vcsize替代。
sort(homework.begin(),homework.end())意为对homework容器中的数从头到尾进行非递减排序。sort是algorithm库中的函数,意为排列。
2.作业完成情况。
本章作业,3-1没有太理解题目的意思。完成了3-2到3-5的编写。
其中3-2从思路上一开始想复杂了,只需要一个向量,找出三个位置(即三段长度),把向量分成长度相等的四段,用sort排序后依次输出就好了。
3-3是一个难题,没能独立完成。借鉴(copy)了别人的代码。其中对输入的单词进行分类与计数的嵌套循环写的尤其好。具有学习价值。特此贴出代码。
//3-3 编写一个程序来报告它的输入中每个不同单词出现的次数
#include<algorithm>
#include<iostream>
#include<vector>
#include<string>
int p33() {
using namespace std;
vector<string> words;
vector<int> counts;//生成容器counts以
typedef vector<string>::size_type vec_sz;
cout << "enter the words: ";
string str;
while (cin >> str)
{
if (str == "end")
break;//当输入end时跳出循环。
//以下循环的思路是:
//将输入的单词按类区分,每一个单词为一类,每输入一个单词,就与已存入向量中的每一类进行比对.
//如果是新词就开始新的计数,如果是出现过的词就在那一类词的计数上加1.
bool found = false;//bool类型,false意为 没有找到新词!
for (vec_sz i = 0; i < words.size(); ++i) {
if (str == words[i]/*此条件为真时,代表没有输入新的词。*/) {
++counts[i];
found = true;
cout <<"i is "<< i << ".";
cout << "wordsize is " << words.size()<<".";//让found=true,这样!found 就是假,就是没有找到新词,就不会把输入的词压进向量里了。
}
}//为什么第二次循环后i还是0??
//第一次输入str时,因为words中不存在内容,因此for循环条件不满足,不会执行循环。当第一个str被存入words,使words.size()=1,此时才会执行循环。
if (!found/*意为 找到新词了!*/) {
words.push_back(str);
counts.push_back(1);
cout << "压进新词" << str << ".";
}//bool类型在这里的作用:判断是否找到了新词。
/*这一段写的真是绝妙!周密,完美的实现了单词之间的比较!并对出现次数进行了计数!*/
}
for (vec_sz i = 0; i < words.size(); ++i) {
cout << words[i] << " appears " << counts[i] << " times" << endl;
}
return 0;
}
首先这里采用了嵌套循环,一个大的while循环中,嵌套了一个循环跳出条件、两个for循环和一个if循环。当输入第一个str时,通过定义bool类型变量found,表示是否找到新的单词。如found值为false,则没有找到新词;如为true,则找到了新词。
通过if(!found)循环,在!found为真时,意为找到新词,执行语句块,将新词压进向量words中,并在向量counts中进行一次从1开始的新的计数。
这个bool的用法第一次接触,整体循环的构建思路也很不错,他是将输入单词按是否相同分为n类,比如输入a b c,则words中就会出现3类数,a b c。而每输入一次都会通过for(vc_sz i=0;i<words.size;i++)来与之前的每一个数进行对比。这里需要注意的点是,每当一个新的str被输入进来,for循环中的i都会进行一次初始化,从而实现了让新输入的str与words中已有的每一个单词进行比对。
3-4 编写一个程序来报告它的输入中最长以及最短的字符串的长度
做这道题时,首先我要定义4个东西,“最长的单词”、“最短的单词”、“最长单词的长度”、“最短单词的长度”。这里体现出编写程序与我们正常思考的一个不同点,在程序编写时,通常要先把概念定义出来,再将值赋予他。
这道题的程序中还有一个点,在对输入的词进行x.size的判断,如果输入词>=最长单词的长度,那么就让他成为新的最长单词,让他的长度成为新的最长长度。但进行最短词的判断时,需要多加一个条件shortest==0||x.size()<=shortest_size。shortest==0这个条件是为了给shortest_size也存入一个值。因为shortest_size的初始值为0,而x.size()是不可能小于0的。只有再加上这个条件之后,才可以让shortest_size的值等于第一个输入字符串的长度。从而开始比较。
3-5 编写一个程序来同时跟踪n个同学的成绩,要求程序能够保持两个向量的同步:
//第一个应保存学生的姓名;第二个保存总成绩,这个总成绩能根据读到的输入来计算。
//读者应当假定家庭作业成绩的个数是固定的。
这道题可能是本章作业里面思路最简单的一道题。但在写程序时仍有一些问题。
我需要创建两个向量namelist和gradelist来分别存储学生的姓名和他们的总成绩,做到两个向量中的值对应输出并不难。只需要用数组就可以做到。但编写程序时,需要注意哪些东西在循环体内,哪些在循环体外。报错就是因为我一开始将创建向量的语句写在了循环体里,导致每次循环都要重新创建一个向量。。
for (int i = 1; i < n; i++) {
cout << n << "位同学你们好,请第" << i << "位同学输入姓名:";
cin >> name;
namelist.push_back(name);//写什么循环呀,直接进就完事了。因为这里不需要while来进行多个name的读入,一次for循环里只读入一次就ok
cout << "你好!" << namelist[i - 1] << "同学。" << endl;
同时还要注意,计数这里i是从1开始计数的,所以在使用数组时要用[i-1]。
3.总结
本章的新的点主要在于向量的概念,bool值的使用,以及对for、while、if循环的进一步理解。需要注意编程时的思路和编写细节,不要钻牛角尖。
继续加油!