附:此笔记是为了记录自己学习《C++ primer》中文版第五版的学习过程,同时督促自己,“希望有一天,自己从来不缺从头再来的勇气”,在此之前看的C++的书都很杂乱,所以想系统性地再认真学一遍,打好基础。
书中使用最多的编译器是GNU编译器4.7.0,本人使用的Dev-C++ 5.11,并对书中的练习进行了相应解答,仅供参考,有错误的地方,欢迎联系我指正,十分感谢。
编写一个程序来解决简单的书店问题。
要求:书店保存所有销售记录的档案,每条记录保存某本书的一次销售的信息(一册或多册)。每条记录包含三个数据项。
0-201-70353-X 4 24.99
第一项是书的ISBN号。第二项是售出的册数,第三项是书的单价。
有时书店老板需要查询此档案,计算每本书的销售量、销售额及评价售价。
思考该程序包含哪些子问题?
定义变量
进行输入和输出
使用数据结构保存数据
检测两条记录是否有相同的ISBN
包含一个循环来处理销售档案中的每条记录
#include
iostream
库中包含两个基础类型istream
和ostream
,分别表示输入和输出。一个流就是一个字符序列,是从IO设备读出或写入IO设备的。
int main( )
{
std::cout<<"Enter two numbers:"<>v1>>v2;
std::cout<<"The sum of"<
cin
标准输入,istream
类型的对象。使用输入运算符>>,该运算符返回其左侧的运算对象,左侧的运算对象必须是一个istream
对象。
cout
标准输出,ostream
类型的对象。使用输出运算符<<,该运算符返回其左侧的运算对象,左侧的运算对象必须是一个ostream
对象。
std::cout<<"Enter two numbers:"<
std::cout
,因此可以写成一行,也可以用两条语句来生成相同的输出:
std::cout<<"Enter two numbers:";
std::cout<
第一个输出运算符给用户打印一条信息,是一个字符串字面值常量,是用一对双引号包围的字符序列。在双引号之间的文本被打印到标准输出。
第二个运算符打印endl
,是一个操纵符的特殊值,作用是结束当前行,并将于设备关联的缓冲区中的内容刷到设备中。
注意 使用标准库中的名字std:: cout
和 std::endl
,而不是直接的cout
和endl
。
前缀std::
指出名字cout
和endl
是定义在名为std
的命名空间(namespace)
中的。命名空间可以帮助我们避免不经意的名字定义冲突,以及使用库中相同名字导致的冲突。标准库定义的所有名字都在命名空间std
中。
通过命名空间使用标准库有一个副作用:当使用标准库中的一个名字时,必须显式说明我们想使用来自命名空间std
中的名字。例如,需要写出std:: cout
,通过使用作用域运算符(::)
来指出我们想使用定义在命名空间std
中的名字cout
。
如果在程序首部声明命名空间using namespace std;
,则在输入、输出就不需要作用运算符进行前缀,直接写cin,cout即可。
编写程序,在标准输出上打印 Hello, World。
#include
int main( )
{
std::cout << "Hello, World" << std::endl;
return 0;
}
我们的程序使用加法运算符+来将两个数相加。编写程序使用乘法运算符*,来打印两个数的积。
#include
int main( )
{
std::cout << "Enter two numbers:" << std::endl;
int v1 = 0, v2 = 0;
std::cin >> v1 >> v2;
std::cout << "The product of " << v1 << " and " << v2
<< " is " << v1 * v2 << std::endl;
return 0;
}
我们将所有输出操作放在一条很长的语句中。重写程序,将每个运算对象的打印操作放在一条独立的语句中。
#include
int main( )
{
std::cout << "Enter two numbers:" << std::endl;
int v1 = 0, v2 = 0;
std::cin >> v1 >> v2;
std::cout << "The product of ";
std::cout << v1;
std::cout << " and ";
std::cout << v2;
std::cout << " is ";
std::cout << v1 * v2;
std::cout << std::endl;
return 0;
}
解释下面程序片段是否合法。如果程序是合法的,它的输出是什么?如果程序不合法,原因何在?应该如何修正?
std::cout << "The sum of " << v1;
<< " and " << v2;
<< " is " << v1 + v2 << std::endl;
不合法,第一、二行不需要分号,删除多余的“;”,修改如下:
std::cout << "The sum of " << v1
<< " and " << v2
<< " is " << v1 + v2 << std::endl;
单行注释 //
界定符对注释 : 以 /*开始, */结束,不能嵌套。当注释界定符跨越多行时,最好能显式指出其内部的程序行都属于多行注释的一部分,可以一个星号开头。
编译一个包含不正确的嵌套注释的程序,观察编译器返回的错误信息。
指出下列哪些输出语句是合法的(如果有的话):预测编译这些语句会产生什么样的结果,实际编译这些语句来验证你的答案(编写一个小程序,每次将上述一条语句作为其主体),改正每个编译错误。
std::cout << "/*";
std::cout << "*/";
std::cout << /* "*/" */;
std::cout << /* "*/" /* "/*" */;
第三行编译出错,改正方法是增加一个引号。输出: /**/ */ /*
用while语句编写程序,实现1到10这10个数之和。
#include
int main( ){
int sum = 0,val = 1;
//只要val的值小于等于10,while循环就会持续执行
while (val <= 10){
sum+= val; //将sum + val赋予sum
++val; //将val 加1
}
std::cout <<"sum of i to 10 inclusive is"
<< sum <
输出结果sum of i to 10 inclusive is 55
while (val <= 10){
sum+= val; //将sum + val赋予sum
++val; //将val 加1
}
循环体由两条语句组成的语句块:
while(condition)
{
statement;
}
while语句的执行过程是交替地检测condition条件,和执行关联的语句statement,直至condition为假时停止。
编写程序,使用while循环将50到100的整数相加。
#include
using namespace std;
void main( )
{
int i=50;
int sum = 0;
while (i >= 50 && i <= 100)
{
sum = sum+i;
i++;
}
cout<
除了++运算符将运算对象的值增加1之外,还有一个递减运算符(–)实现将值减少1。编写程序,使用递减运算符在循环中按递减顺序打印出10到0之间的整数。
#include
using namespace std;
void main()
{
int i=10;
while (i >= 0 && i <= 10)
{
cout<
编写程序,提示用户输入两个整数,打印出这两个整数所指定的范围内的所有整数。
#include
using namespace std;
int main( )
{
int a,b;
std::cout<<"输入两个整数"<>a>>b;
if(a>b)
{
int temp;
temp=a;
a=b;
b=temp;
}
while(a<=b)
{
cout<
用for语句编写程序,实现1到10这10个数之和。
#include
int main( ){
int sum = 0;
//从1加到10
for (int val=1;val<=10;val++){
sum+= val; //等价于sum= sum+val
}
std::cout <<"sum of i to 10 inclusive is"
<< sum <
简要重述一下for 循环的总体执行流程:
下面的for循环完成了什么功能?sum的终值是多少?
int sum = 0;
for (int i = -100; i <= 100; ++i)
sum += i;
从 -100 加到 100 ,sum 的终值为 0。
#include
using namespace std;
int main( )
{
int a,b;
std::cout<<"输入两个整数"<>a>>b;
if(a>b)
{
int temp;
temp=a;
a=b;
b=temp;
}
for(int i=a;i<=b;i++)
{
cout<
对比for循环和while循环,两种形式的优缺点各是什么?
在for循环中,循环控制变量的初始化和修改都放在语句头部分,形式较简洁,且特别适用于循环次数已知的情况。在while循环中,循环控制变量的初始化一般放在while语句之前,循环控制变量的修改一般放在循环体中,形式上不如for语句简洁,但它比较适用于循环次数不易预知的情况(用某一条件控制循环)。两种形式各有优点,但它们在功能上是等价的,可以相互转换。
if语句统计在输入中每个值连续出现了多少次。
#include
int main( )
{ // currVal是我们正在统计的数;我们将读入的新值存入val
int currval = 0,val =0;
//读取第一个数,并确保确实有数据可以处理
if (std::cin>>currval) {
int cnt=1; //保存我们正在处理的当前值的个数
while (std::cin >> val) { // 读取刺余的数
if (val == currval)
++cnt; // 如果值相同,将cnt加1
else { //否则,打印前一个值的个数
std::cout << currval <<"occurs "
<< cnt <<"times" << std::endl;
currval=val; //记住新值
cnt = 1; //重置计数器
}
} // while循环在这里结束
//记住打印文件中最后一个值的个数
std::cout << currval << "occurs"
<< cnt<< "times" << std::endl;
} //最外层的if语句在这里结束
return 0;
}
输出与书本结果不一致。????
在后面的章节有详细讲解,这个部分是直接用了类的特性,不关心它是如何实现的,只需知道类对象可以执行什么操作即可。采用.h
作为头文件的后缀
#include
#include "sales_item.h"
int main()
{
sales_ item total; //保存下一条交易记录的变量
//读入第一条交易记录,并确保有数据可以处理
if (std::cin >> total) {
sales_ item trans; //保存和的变量
//读入并处理剩余交易记录
while (std::cin >> trans) {
//如果我们仍在处理相同的书
if (total.isbn()== trans. isbn())
total += trans; // 更新总销售额
else {
//打印前一本书的结果
std::cout << total << std::endl;
total = trans; //total现在表示下一本书的销售额
}
}
std::cout << total << std::endl; // 打印最后一本书的结果
} else {
//没有输入!警告读者
std: :cerr << "No data?!" << std: :endl ; .
return -1; //表示夫败
}
return 0;
}
练习1.20
在网站http://www.informit.com/title/032174113 上,第1章的代码目录包含了头文件 Sales_item.h
。将它拷贝到你自己的工作目录中。用它编写一个程序,读取一组书籍销售记录,将每条记录打印到标准输出上。
#include
#include "Sales_item.h"
using namespace std;
int main()
{
Sales_item item;
cin >> item;
cout << item << endl;
return 0;
}
练习1.21
读取两个ISBN相同的Sales_item 对象,输出它们的和。
#include
#include "Sales_item. h"
int main( )
{
Sales_ item iteml, item2;
std::cin >> iteml >> item2;
//读取一对交易记录
//首先检查item1和item2是否表示相同的书
if (iteml.isbn() == item2.isbn()) {
std: :cout << iteml + item2 << std: :endl; // 打印它们的和
return 0; //表示成功
} else{
std::cerr << "Data must refer to same ISBN" //cerr通常用来输出警告和错误消息,也称为标准错误
<< std::endl;
return -1; //表示失败
}
练习1.22
编写程序,读取多个具有相同 ISBN 的销售记录,输出所有记录的和。
#include
#include "Sales_item.h"
int main()
{
Sales_item total;
if (std::cin >> total)
{
Sales_item trans;
while (std::cin >> trans)
{
if (total.isbn() == trans.isbn())
total += trans;
else
{
std::cout << total << std::endl;
total = trans;
}
}
std::cout << total << std::endl;
}
else
{
std::cerr << "No data?!" << std::endl;
return -1;
}
return 0;
}
练习1.23
编写程序,读取多条销售记录,并统计每个 ISBN(每本书)有几条销售记录。
#include
#include "Sales_item.h"
int main()
{
Sales_item currItem, valItem;
if (std::cin >> currItem)
{
int cnt = 1;
while (std::cin >> valItem)
{
if (valItem.isbn() == currItem.isbn())
{
++cnt;
}
else
{
std::cout << currItem << " occurs " << cnt << " times " << std::endl;
currItem = valItem;
cnt = 1;
}
}
std::cout << currItem << " occurs " << cnt << " times " << std::endl;
}
return 0;
}