C++控制流和类介绍,并实现一个基于C++的书店程序

1.1 设计一个简单的图书管理程序

这是我们学完本章需要实现的!

1.2初识输入输出

在C++里面提供了一个全面的标准库来提供输入和输出机制,书中很多实例都使用到了iostream库,这个库里面包含了两个基础类型ostream和istream,分别表示输入流和输出流,一个流就是一个字符序列,是从IO设备里面读出或者写入的,术语流所表达的就是,随着时间的推移字符是顺序生成或消耗的。
标准库里面定义了4个IO对象,cin是标准输入,cout是标准输出,还有两个ostream类型的对象,分别是cerr和clog分别用来输出错误信息和程序运行时的一般性信息。
在书店系统中,我们需要将多条记录合并成单一的汇总记录,我们首先来一个两数相加的实现

#include<iostream>
using namespace std;
int main(){
	cout<<"Enter two numbers"<<endl;
	int v1=0, v2=0;
	cin>>v1>>v2;
	cout<<"sum is"<<v1+v2<<endl;
	return 0;
}

上面加入了一个using namespace std;是指出下面的代码是定义在std的命名空间中,命名空间可以帮助我们避免不经意的名字定义冲突,以及使用库中相同名字导致的冲突,标准库定义的所有名字都在命名空间std中,通过命名空间使用标准库有一个副作用:当使用标准库中的一个名字时,必须显式说明我们想使用来自命名空间std中的名字,比如std::cout,这时我们就可以直接在头文件下面使用using namespace std;来访问标准库里面的名字
下面我们使用g++进行编译生成可执行文件
在这里插入图片描述

1.3注释简介

C++中有两种注释:单行注释和界定符对注释

//这是一条注释

/*
这中间的全是注释
*/

很简单是吧

1.4控制流

语句一般都是顺序执行的:语句块第一句先执行,然后第二句,依此类推,为了我们写出更为复杂的执行路径,提供给了我们多种不同的流控制语句。

1.4.1while语句

while语句反复执行一段代码,直到给定条件为假为止,我们可以用while来编写一段程序,求出1到10的和。

#include<iostream>
using namespace std;
int main(){
    int sum=0,val=0;
    while (val <= 10)
    {
        sum += val;//将sum+val的值赋予sum
        ++val;//将val加1,等价于val=val+1
    }
    cout<<"sum is :"<<sum<<endl;
    return 0;
}

在这里插入图片描述

while (condition)
	statement

while语句的执行过程是交替的检测condition条件和执行关联的statement,直至condition为假时停止,只要condition为真,statement就会执行,当执行完statement,会再次检测condition。while语句交替的检测condition和执行statement,直至condition为假为止。

1.4.2 for 语句

在while循环例子中,使用了val来控制循环执行的次数,我们在循环条件中检测val的值,在while循环体中将val递增。
这种循环条件中检测变量、在循环体中递增变量的模式使用非常频繁,所以C++专门定义了第二种循环语句—for语句,来简化符合这种模式的语句,我们用for语句来重写从1加到10的程序。

#include<iostream>
using namespace std;
int main(){
    int sum = 0;
    for (int val = 1; val <= 10; ++val)
    {
        sum +=val;
    }
    cout << "sum is :"<<sum<<endl;
    return 0;
}

每个for语句都包括两个部分,循环头和循环体。循环头控制循环体的执行次数,它由三个部分组成:一个初始化语句、一个循环条件以及一个表达式。在本例中,初始化语句为int val = 1,初始化语句只有在for循环体入口执行一次,循环条件是 val <= 10,只要val小于等于10就会执行for循环体,表达式是++val,使用前缀递增运算符将val的值加1,表达式在for循环体之后执行,执行完表达式之后,for语句重新检测循环条件,如果val的新值仍然小于等于10,再次执行for循环体,执行完循环体之后再次将val的值增加1,直到循环条件为假。

1.4.3读取数量不定的输入数据

在前面实现了1到10求和,扩展一个程序自然的方向是实现对用户输入的一组数求和,在这种情况下,我们预先并不能知道要对多少个数求和,这就需要不断的读取数据直至没有新的输入为止:

#include<iostream>
using namespace std;
int main(){
    int sum = 0,value = 0;
    while (cin >> value)//只要有cin进数字就为真
    {
        sum += value;
    }
    cout << "sum is :"<<sum<<endl;
    return 0;
}

执行结果
我们使用sum来作为累加的对象,value用来保存用户每一个输入的数,读取操作在while的循环条件中完成,cin>>value此表达式从标准输入读取到每一个数记录在value中,实际上此循环条件检测的是cin。
当我们使用一个istream对象作为条件的时候,其效果是检测流的状态,如果流是有效的,即流未遇到错误,那么检测成功条件为真。当遇到文件结束符,或者遇到一个无效输入时(例如读入的值不是一个整数),istream对象的状态就会变成无效,这是while检测到条件为假。
因此while循环会一直执行直到遇到文件结束符或输入错误,在centos中文件结束符是Ctrl+D,一旦条件为假,循环就结束,然后执行下一语句,打印出sum的值和一个endl。

1.4.4 if语句

C++提供了if语句来支持条件执行,我们可以用if语句写一个程序,来统计输入中每个值连续出现的次数:

#include<iostream>
using namespace std;
int main(){
	//currVal是正在统计出现次数的数,val保存从输入读取到的每一个数
    int currVal = 0,val = 0;
    //读取第一个数,并确保确实有数据可以处理,也就是让if的条件为真,让继续执行代码段
    if (cin >> currVal){
        int cnt = 1; //保存正在处理的当前值的个数
        while (cin >> val) //读取剩余的数
        	{
            if(val == currVal) //如果值相同
                ++cnt; //将cnt加1
            else //如果值不相同,就打印前一个值的个数,然后把新输入的值给currVal重新对cnt赋值1后,跳出当前的这个if
            {
                cout << currVal<<" occurs "<<cnt<<" times "<<endl;
                currVal = val; //记住新值
                cnt = 1; //重置计数器
            }   
        }
        //记住打印文件中最后一个值的个数
        cout << currVal<<" occurs "<<cnt<<" times "<<endl;
    }
    return 0;
}

保证输入不能为空。与while语句类似,if也对一个条件进行求值。第一条if语句的条件是读取一个数值存入currVal中。如果读取成功,则条件为真,继续执行条件语句之后的语句块。
定义cnt来统计每一个数值连续出现的次数,用while循环反复的读取标准输入的整数。
在while内的if语句中使用到了相等运算符(==)来检测val是否等于currVal,如果等于,就执行紧跟在条件之后的语句。这条语句将cnt+1,表面我们又一次看到了currVal。
如果条件为假,那就是新读入的val不等于currVal,则执行else之后的语句。这条语句是将我们刚刚统计完的值的出现次数打印显示出来。然后赋值语句将cnt重置为1,将currVal重置为刚刚读取到的值val。
在读这段代码的时候,一定要清楚什么时候条件为假,什么时候条件为真,这样就可以知道到底循环的过程中代码都做了什么。

1.5 类介绍

在解决书店程序之前,我们还需要了解的唯一一个C++特性,就是定义一个数据结构(data structure)来表示销售数据。在C++中,我们通过定义一个类(class)来定义自己的数据结构。一个类定义了一个类型,以及与其相关联的一组操作。类机制是C++最重要的特性之一。实际上,C++最初的一个设计焦点就是能定义使用上像内置类型一样自然的类类型(class type)。
为了使用类,我们需要了解三件事:
1.类名是什么?
2.它是在哪里定义的?
3.它支持什么操作?
对于书店程序来说,我们假定类名为Sales_item,头文件Sales_item.h中已经定义了这个类。
为了使用标准库设施,我们必须包含相关的头文件。类似的,我们也需要使用头文件来访问为自己的应用程序所定义的类。习惯上,头文件根据其中定义的类的名字来命名。

1.5.1 Sales_item类

Sales_item类的作用是表示一本书的销售额、售出册数和平均售价。现在先不关心数据如何存储和计算。为了使用一个类,我们不必关心它是如何实现的,只需要知道类对象可以执行什么操作。
Sales_item类定义了一个名为Sales_item的类型。与内置类型一样,我们可以定义类类型的变量:

Sales_item item;

就是表达item是一个Sales_item类型的对象,除此之外我们还可以:
1.调用一个名为isbn的函数从一个Sales_item对象中提取ISBN书号。
2.使用加法运算符将两个Sales_item对象相加。两个对象必须表示同一本书(相同的ISBN)。加法结果是一个新的Sales_item对象,其ISBN与两个运算对象相同,其总销售额和售出册数则是两个运算对象的对应值之和

读写Sales_item

我们已经知道了可以对Sales_item进行什么操作,下面进行实操。例如:下面程序从标准输入读入数据,存入一个Sales_item对象中,然后将Sales_item的内容写回到标准输出:

#include <iostream>
#include"Sales_item.h"
using namespace std;
int main(){
    Sales_item book;
    cin >> book;//读入ISBN号、售出数量、销售单价
    cout << book << endl;//输出ISBN号、售出册数、总销售额、销售单价
    return 0;
}

在这里插入图片描述
此程序从两个#include指令开始,一个是用<>包围的标准库头文件,另一个是" "双引号包围的非标准库头文件。
在main中定义了一个名为book的对象,用来保存从标准输入读取的数据,下一条语句读取数据存入对象中,第三句打印然后换行。

Sales_item对象的加法

下面将两个Sales_item对象相加:

#include <iostream>
#include"Sales_item.h"
using namespace std;
int main(){
    Sales_item item1,item2;
    cin >> item1>>item2;
    cout << item1+item2<< endl;
    return 0;
}

在这里插入图片描述

1.5.2 初识函数成员

将两个Sales_item对象相加的程序首先应该检查两个对象是否有相同的ISBN,方法如下:

#include <iostream>
#include"Sales_item.h"
using namespace std;
int main(){
    Sales_item item1,item2;
    cin >> item1>>item2;
    if (item1.isbn() == item2.isbn())
    {
        cout << item1+item2<< endl;
        return 0;//表示成功
    }else{
        cerr<< "Data must refer to same ISBN"<<endl;
        return -1; //表示失败
    }
}

如果两个对象的ISBN号相同则可以加后返回0,表示成功,如果条件失败,则打印一条错误信息,并返回一个错误标识。
在if (item1.isbn() == item2.isbn())中,调用名为isbn的成员函数,成员函数是定义为类的一部分,也被叫做方法。

1.6 书店程序

此程序会将每个ISBN的所有数据合并起来,存入名为total的变量中。我们使用另一个名为trans的变量保存读取的每条销售记录。如果trans和total指向相同的ISBN,我们会更新total的值。否则,我们会打印total的值,并将其重置为刚刚读取的数据(trans):

#include <iostream>
#include "Sales_item.h"
using namespace std;
int main() 
{
    Sales_item total; // 保存和的变量
    // 读入第一条交易记录,并确保有数据可以让if条件为真
    if (cin >> total) {
		Sales_item trans; // 为保存下一条交易记录创建结构体变量
        // 读入销售记录并处理剩余交易记录
        while (cin >> trans) {
            if (total.isbn() == trans.isbn())//如果仍在处理相同的书 
                total += trans; // 更新总销售额
            else { 
                cout << total << endl;// 打印前一本书的结果  
                total = trans;  // total现在表示下一本书的销售额
            }
		}
        cout << total << endl; // 打印最后一本书的结果
    } else {
        cerr << "No data?!" << endl;//如果没有输入抛出错误提示
        return -1;  // 表示失败
    }
    return 0;
}

在这里给大家说一下Linux系统下文件重定向的方法,这种机制支持我们将标准输入和输出关联起来:
程序name outfile
上述命令会从一个名为infile的文件读取到销售记录,然后将输出结果写入到一个名为outfile的文件中,这两个文件都位于当前目录中。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤夜寒光

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值