C++ Primer Exercise 1.23 (英文版P24)本来是一个简单的Sales_item小程序,但是我发现如果输入时是一行一行打进去的而非复制进入界面的(可能复制就不会出什么问题吧),就会在输入新的ISBN后立刻输出之前一个ISBN的相关信息,因而影响程序效果(例如第2个展示程序第101行)。所以我做出了一定的修改。
对于使用vector的三种方案,均以Exercise 2.41(1.5.2)为案例。
使用array(数组)
其实用数组并不好,因为我们并不知道ISBN的数量,应该使用vector。但这是还没学到后面的时候做的,以前听说有数组,于是就这样操作了。(之后提供三种用vector解决的方案)
#include <iostream>
#include "Sales_item.h"
using namespace std;
int main()
{
Sales_item item, init; //'init' refers to 'initial'
int s = 1;
int t = 0;
int sum[1000] ;
string name[1000];
//This means there should be no more than 1000 ISBN numbers.
for (int i = 0; i <= 999; i++)
sum[i] = 0;
cout << "Please enter control-z when finishing inputting information." << endl;
cin >> init;
while (cin >> item)
{
if (item.isbn() == init.isbn())
s++;
else
{
sum[t] = s; //store occurring times in sum[1000]
name[t] = init.isbn(); //store ISBN in name[1000]
s = 1;
t++;
init = item;
}
}
for (int j = 0; j < t; j++)
{
if (sum[j] != 1)
cout << name[j] << " occurs " << sum[j] << " times" << endl;
else cout << name[j] << " occurs 1 time" << endl;
}
if (s != 1)
cout << init.isbn() << " occurs " << s << " times" << endl;
else cout << init.isbn() << " occurs 1 time" << endl;
cout << "@Teddy van Jerry" << endl;
return 0;
}
/*
USED FOR TEST:
Example 1:
0-201-78345-1 2 3
0-201-78345-1 2 4
0-201-78345-1 3 4
0-201-78345-2 3 4
0-201-78345-2 4 3
0-201-78345-3 3 4
0-201-78345-3 4 5
0-201-78345-4 1 3
0-201-78345-5 1 2
Result:
0-201-78345-1 occurs 3 times
0-201-78345-2 occurs 2 times
0-201-78345-3 occurs 2 times
0-201-78345-4 occurs 1 time
0-201-78345-5 occurs 1 time
@Teddy van Jerry
Example 2:
0-201-78345-1 2 3
Result:
0-201-78345-1 occurs 1 time
@Teddy van Jerry
Example 3:
0-201-78345-1 2 3
0-201-78345-2 3 4
Result:
0-201-78345-1 occurs 1 time
0-201-78345-2 occurs 1 time
@Teddy van Jerry
Example 4:
0-201-78345-1 2 3
0-201-78345-1 2 4
0-201-78345-1 3 4
0-201-78345-2 3 4
0-201-78345-2 4 3
0-201-78345-3 3 4
0-201-78345-3 4 5
0-201-78345-4 1 3
0-201-78345-5 1 2
0-201-78345-5 1 2
Result:
0-201-78345-1 occurs 3 times
0-201-78345-2 occurs 2 times
0-201-78345-3 occurs 2 times
0-201-78345-4 occurs 1 time
0-201-78345-5 occurs 2 times
@Teddy van Jerry
ALL RIGHTS RESERVED 2020(C)Teddy van Jerry
*/
此处用了数组暂时存储信息,最后再输出。(默认ISBN数应该不会超过1000)
此外还有次数time是否要复数s,要对init.isbn()的值是否为1判断。这也是一个小细节。
在Exercise 2.41(1.5.2)中同样有类似的问题,这次确定复制进去仍然会出现一下程序101行的情况。
#include <iostream>
#include <string>
using namespace std;
int main()
{
//define class Sales_data
struct Sales_data {
string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
}data, init;
string name[1000];
unsigned sum[1000];
double price = 0.0;
int s = 1;
int t = 0;
for (int i = 0; i <= 999; i++)
sum[i] = 0;
cout << "Please enter control-z when finishing inputting information." << endl;
//input
cin >> init.bookNo >> init.units_sold >> price;
while (cin >> data.bookNo >> data.units_sold >> price)
{
if (data.bookNo != init.bookNo)
{
name[t] = init.bookNo; //store ISBN(i.e. bookNo) in string[1000]
sum[t] = s; //store occurring times in sum[1000]
++t;
s = 1;
init = data;
}
else ++s; //count
}
//output
for (int i = 0; (i <= 999) && sum[i] != 0; i++)
{
if (sum[i] == 1) cout << name[i] << " occurs 1 time" << endl;
else cout << name[i] << " occurs " << sum[i] << " times" << endl;
}
//Don't forget the last bookNo!
if (s == 1) cout << data.bookNo << " occurs 1 time" << endl;
else cout << data.bookNo << " occurs " << s << " times" << endl;
cout<< "@Teddy van Jerry" << endl;
return 0;
}
/*
USED FOR TEST:
Example 1:
0-201-78345-1 2 3
0-201-78345-1 2 4
0-201-78345-1 3 4
0-201-78345-2 3 4
0-201-78345-2 4 3
0-201-78345-3 3 4
0-201-78345-3 4 5
0-201-78345-4 1 3
0-201-78345-5 1 2
Result:
0-201-78345-1 occurs 3 times
0-201-78345-2 occurs 2 times
0-201-78345-3 occurs 2 times
0-201-78345-4 occurs 1 time
0-201-78345-5 occurs 1 time
@Teddy van Jerry
Example 2:
0-201-78345-1 2 3
Result:
0-201-78345-1 occurs 1 time
@Teddy van Jerry
Example 3:
0-201-78345-1 2 3
0-201-78345-2 3 4
Result:
0-201-78345-1 occurs 1 time
0-201-78345-2 occurs 1 time
@Teddy van Jerry
Example 4:
0-201-78345-1 2 3
0-201-78345-1 2 4
0-201-78345-1 3 4
0-201-78345-2 3 4
0-201-78345-2 4 3
0-201-78345-3 3 4
0-201-78345-3 4 5
0-201-78345-4 1 3
0-201-78345-5 1 2
0-201-78345-5 1 2
Result:
0-201-78345-1 occurs 3 times
0-201-78345-2 occurs 2 times
0-201-78345-3 occurs 2 times
0-201-78345-4 occurs 1 time
0-201-78345-5 occurs 2 times
@Teddy van Jerry
Unpleasant mixture of input and output of Example 4:
Please enter control-z when finishing inputting information.
0-201-78345-1 2 3
0-201-78345-1 2 4
0-201-78345-1 3 4
0-201-78345-2 3 4
0-201-78345-1 occurs 3 times
0-201-78345-2 4 3
0-201-78345-3 3 4
0-201-78345-2 occurs 2 times
0-201-78345-3 4 5
0-201-78345-4 1 3
0-201-78345-3 occurs 2 times
0-201-78345-5 1 2
0-201-78345-4 occurs 1 time
0-201-78345-5 1 2
^Z
0-201-78345-5 occurs 2 times
@Teddy van Jerry
ALL RIGHTS RESERVED 2020(C)Teddy van Jerry
*/
在Exercise 2.41(1.6)中可以这样修改:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//define class Sales_data
struct Sales_data {
string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
}total, trans;
double price;
unsigned t = 0;
double revenue_print[1000];
unsigned units_sold_print[1000];
string bookNo_print[1000];
for (int i = 0; i <= 999; i++)
units_sold_print[i] = 0;
cout << "Please enter control-z when finishing inputting information." << endl;
//input
if (cin >> total.bookNo >> total.units_sold >> price)
{
total.revenue = price * total.units_sold;
while (cin >> trans.bookNo >> trans.units_sold >> price)
{
if (total.bookNo == trans.bookNo)
{
total.units_sold += trans.units_sold;
total.revenue += price * trans.units_sold;
}
else
{
//store information
bookNo_print[t] = total.bookNo;
units_sold_print[t] = total.units_sold;
revenue_print[t] = total.revenue;
//reset for next ISBN
total.bookNo = trans.bookNo;
total.units_sold = trans.units_sold;
total.revenue = price * trans.units_sold;
t++;
}
}
//output
for (int i = 0; (i <= 999) && units_sold_print[i] != 0; i++)
cout << bookNo_print[i] << " " << units_sold_print[i] << " " << revenue_print[i] << " " << revenue_print[i] / units_sold_print[i] << endl;
//Don't forget the last book!
cout << trans.bookNo << " " << total.units_sold << " " << total.revenue << " " << total.revenue / total.units_sold << endl;
}
else
{
cerr << "no data?!" << endl;
return -1;
}
cout << "@Teddy van Jerry" << endl;
return 0;
}
/*
USED FOR TEST:
Example 1:
0-201-78345-X 3 20.00
0-201-78345-X 2 25.00
Result:
0-201-78345-X 5 110 22
@Teddy van Jerry
Example 2:
0-201-78345-X 3 20.00
0-201-78345-X 2 25.00
0-201-78345-Y 3 20.00
0-201-78345-Y 2 25.00
Result:
0-201-78345-X 5 110 22
0-201-78345-Y 5 110 22
@Teddy van Jerry
ALL RIGHTS RESERVED 2020(C)Teddy van Jerry
*/
使用vector和[ ]operator
这样和数组的方法比较接近:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
//define class Sales_data
struct Sales_data {
string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
}data, init;
vector<string> name;
vector<unsigned> sum;
double price = 0.0;
int s = 1;
int t = 0;
cout << "Please enter control-z when finishing inputting information." << endl;
//input
cin >> init.bookNo >> init.units_sold >> price;
while (cin >> data.bookNo >> data.units_sold >> price)
{
if (data.bookNo != init.bookNo)
{
name.push_back(init.bookNo); //store ISBN(i.e. bookNo) in name
sum.push_back(s); //store occurring times in sum
++t;
s = 1;
init = data;
}
else ++s; //count
}
//output
for (int i = 0; i!=sum.size(); i++)
{
if (sum[i] == 1) cout << name[i] << " occurs 1 time" << endl;
else cout << name[i] << " occurs " << sum[i] << " times" << endl;
}
//Don't forget the last bookNo!
if (s == 1) cout << data.bookNo << " occurs 1 time" << endl;
else cout << data.bookNo << " occurs " << s << " times" << endl;
cout << "@Teddy van Jerry" << endl;
return 0;
}
使用vector和range for
这个有些失败,好像 range for 中不得不使用 iterator。但 range for 在有些场合还是非常简洁的。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
//define class Sales_data
struct Sales_data {
string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
}data, init;
vector<string> name;
vector<unsigned> sum;
double price = 0.0;
int s = 1;
int t = 0;
cout << "Please enter control-z when finishing inputting information." << endl;
//input
cin >> init.bookNo >> init.units_sold >> price;
while (cin >> data.bookNo >> data.units_sold >> price)
{
if (data.bookNo != init.bookNo)
{
name.push_back(init.bookNo); //store ISBN(i.e. bookNo) in name
sum.push_back(s); //store occurring times in sum
++t;
s = 1;
init = data;
}
else ++s; //count
}
//Don't forget the last bookNo!
name.push_back(data.bookNo);
sum.push_back(s);
//output
auto name_print = name.begin();
for (auto c:sum)
{
if (c == 1) cout << *name_print << " occurs 1 time" << endl;
else cout << *name_print << " occurs " << c << " times" << endl;
++name_print;
}
return 0;
}
使用vector和iterator
这个使用起来就比前面那个自然很多:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
//define class Sales_data
struct Sales_data {
string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
}data, init;
vector<string> name;
vector<unsigned> sum;
double price = 0.0;
int s = 1;
int t = 0;
cout << "Please enter control-z when finishing inputting information." << endl;
//input
cin >> init.bookNo >> init.units_sold >> price;
while (cin >> data.bookNo >> data.units_sold >> price)
{
if (data.bookNo != init.bookNo)
{
name.push_back(init.bookNo); //store ISBN(i.e. bookNo) in name
sum.push_back(s); //store occurring times in sum
++t;
s = 1;
init = data;
}
else ++s; //count
}
//Don't forget the last bookNo!
name.push_back(data.bookNo);
sum.push_back(s);
//output
auto name_print = name.begin();
auto sum_print = sum.begin();
while(name_print != name.end())
{
if (*sum_print == 1) cout << *name_print << " occurs 1 time" << endl;
else cout << *name_print << " occurs " << *sum_print << " times" << endl;
++name_print;
++sum_print;
}
return 0;
}
See also
Teddy van Jerry 的导航页
【C++ Primer(5th Edition) Exercise】练习程序 - Chapter1(第一章)
【C++ Primer(5th Edition) Exercise】练习程序 - Chapter2(第二章)