编写第一个简单的C++程序

1、引言

学习一门新的语言最好的方法,就是练习编程。在这里,我们将编写一个程序去解决简单的书店问题。

问题如下:

我们的书店保存所有销售记录的档案,每条记录保存某本书一次的销售信息(一册或者多册)。

每天记录包括三个数据项:        0-201-70353-X        4        24.99

第一项是书的ISBN号(一本书的唯一标识),第二本书是售出的册数,第三项是书的单价。

任务:

书店老板需要查询此档案,计算每本书的销售量、销售额以及平均售价。

虽然我们还没有编写这个程序,但显然它必须满足如下要求:

  • 定义变量
  • 进行输入和输出
  • 使用数据结构保存数据
  • 检测两条记录是否有相同的ISBN
  • 使用一个循环来处理销售档案中的每一条数据

1.1        编写一个简单的C++程序

每个C++程序至少有一个或多个函数,其中一个必须命名为mainOS(operation system)是通过调用main函数来运行整个C++程序。

函数的定义包含四个部分:

  • 返回类型
  • 函数名
  • 括号中的形参列表
  • 函数体

        下面是一个简单的main函数示例:

作用:

        什么也不干,只是给操作系统返回一个值。

int main()
{
    return 0;
}

注释:

  • main 函数的形参列表是空的(但是也有其他其他的形参类型,后面我们会介绍
  • main 函数的返回类型必须为 int(当 return 语句包含一个值的时候,此返回值的类型必须与函数的返回类型保持一致)

重要概念:类型

一种类型不仅定义数据元素的内容,还定义了这种类型上可以进行的运算。程序所处理的数据都保存在变量中,而每一个变量都有其自己的数据类型。

1.1.1        编译、运行程序

                        略

1.1练习

  1. 查阅你使用的编译器文档,确定它所使用的文件命名约定。编译并允许main函数
  2. 改写程序,让main函数返回-1。返回-1通常是程序错误的标识。重新编译并允许你的程序,观察你的系统如何处理main返回的错误标识

 1.2        初识输入输出

C++并未定义任何输入输出(I/O)的语句,取而代之,是一个全面的标准库来提供I/O机制。

常用头文件的解释:

#include<iostream>

注释:

  • 这里使用了iostream
  • iostream 库中包含两个基础类型istreamostream,分别表示输入流和输出流。一个流(随着时间的推移,字符是顺序生成的或者顺序消耗的)就是一个字符序列,是从I/O设备读出或者写入I/O设备的。
  • #include是告诉编译器我们想要使用iostream
  • #include指令必须出现在所有的函数之外
1.2.1        标准输入输出对象:

C++提供了4个I/O对象:

  • cin,标准输入对象,类型是istream
  • cout,标准输出对象,类型是ostream
  • cerr,标准错误(用来输出警告和错误信息),类型是ostream
  • clog,输出程序运行时的一般信息

仔细思考:

系统将程序所运行的窗口和这些对象关联起来。当我们读取cin的时候,数据将从程序正在运行的窗口读入,当我们向cout、cerr、clog写入数据时,将会写到同一窗口。

1.2.2        像流中写入数据
std::cout<<"Enter two numbers"<<std::endl;

注释:

  • 使用输出运算符(<<) 在标准输出上打印消息
  • (<<) 运算符接受两个运算对象:左侧的运算对象必须是一个ostream类型的对象,右侧的运算对象是要打印的值。
  • 输出语句中使用了两次(<<)运算符,因为此运算符返回左侧的运算对象,因此第一个运算的输出结果就成为左侧运算对象。
  • endl 是称为操纵符的特殊值。作用是“结束当前行”,并将与设备关联的缓冲区中的内容刷到设备中。缓冲刷新操作可以保证到目前位置的所有输出都真正写入输出流中,而不是仅停留在内存等待写入流。
  • std::cout 和 std::endl,前缀std:: 指出了名字cout和endl是定义在名为std的命名空间中。当我们需要使用标准库的一个名字时,必须通过作用域运算符(::)显示的说明来自命名空间std的名字。

警告:

程序员在调试时添加打印语句,这类语句要保证“一直刷新流”。否则,如果程序崩溃,输出还可能留在缓冲区,从而导致程序崩溃位置的错误推断。

1.2.3        从流中读取数据
int v1=0;
int v2=0;
std::cin>>v1>v2;

注释:

  • 输入运算符(>>)与输出运算符类似,它接受一个istream作为其左侧运算对象,接受一个对象作为其右侧的运算对象。从给定的istream读入数据,并存入给定对象中。与输出运算符类似,输入运算符返回其左侧运算对象作为其运算结果。

1.3        注释简介

1.3.1        C++注释的种类
  • 单行注释:以双斜线(//)开始,以换行符结束。
  • 界定符对注释:以(/*)开始,以(*/)结束。编译器将落在/*和*/之内的所有内容当作注释

注意:注释不要嵌套

1.4        控制流

语句一般都是顺序执行的,语句块的第一条语句首先执行,然后是第二条语句,以此类推。但是C++程序设计语言,提供了多种不同的控制流语句,允许我们写出更为复杂的执行路径。

1.4.1        while语句

while语句会反复的执行一段代码,直到给定条件为假为止。

#include<iostream>
using namespace std;
int main()
{
	
	int sum = 0, val = 1;
	while (val <= 10)
	{
		sum += val;
		++val;
	}
	cout << "Sum of 1 to 10 inclusive is " << sum << endl;
	return 0;
}

while语句的形式:

while(condition)

statement;

注释:

  • 复合赋值运算符(+=),将右侧的运算对象加到左侧上,将结果保存在左侧的运算对象中
  • 前缀递增运算符(++),将运算对象的值增加1。
1.4.2        for语句
#include<iostream>
using namespace std;
int main()
{
	
	int sum = 0;
	for (int val = 1; val <= 10; ++val)
	{
		sum += val;
	}
	cout << "Sum of 1 to 10 inclusive is " << sum << endl;
	return 0;
}

for语句的形式:循环头和循环体。

循环头:控制循环体的执行次数,由三个部分组成:一个初始化语句,一个循环条件以及一个表达式。

循环体:执行具体的语句。

注释:

  • 初始化语句:int val=1;
  • 循环条件:val<=10;
  • 表达式:++val;
  • 循环体在每次执行前都会先检查循环条件,只要条件满足就会执行循环体,表达式在循环体执行之后再执行。直到检查条件不满足,就会退出循环。
1.4.3        读入数量不定的输入语句
#include<iostream>
using namespace std;
int main()
{
	
	int sum = 0;
	int value = 0;
	while (cin >> value)
	{
		sum += value;

	}
	cout << "Sum is : " << sum << endl;
	return 0;
}

注释:

  • 当我们使用一个istream对象作为条件,其效果就是检测流的状态。如果流是有效的,即流未遇到错误,那么检测成功;当遇到文件结束符,或者遇到一个无效的输入(这里指的是输入的值不是一个整数),istream对象的状态会变成无效,istream对象会使循环条件为假。

1.4.4        if语句
#include<iostream>
using namespace std;
int main()
{
	
	int currVal = 0, val = 0;
	int cnt = 0;
	if (cin >> currVal)
	{
		cnt = 1;
		while (cin >> val)
		{
			if (val == currVal)
			{
				++cnt;
			}
			else
			{
				cout << currVal << " occurs " << cnt << " times " << endl;
				currVal = val;
				cnt = 1;
			}
		}
		cout << currVal << " occurs " << cnt << " times " << endl;
	}

	return 0;
}

注释:

  • 赋值运算符(=)和相等运算符(==),所使用的场合是完全不同的。

1.5        类简介

说明:在解决书店程序之前,我们还需要了解C++的重要特性,就是如何定义一个数据结构来表示自己的销售。在C++中,通常定义一个来定义自己的数据结构。一个定义了一种类型,以及在此类型上的一组操作

1.5.1        Sales_item类

        Sales_item类的作用就是表示一本书的总销售额,售出的册数,以及平均售价。我们现在不关心这些数据如何存储,如何计算。为了使用一个类,我们不必关心它是如何实现的,只需要知道类对象可以执行什么操作。

        每一个类实际上都是定义了一个新的数据类型,类型名就是类名。和内置数据类型一样,我们可以定义类类型的变量。

        Sales_item类可以执行的操作:

  • 定义一个Sales_item类型的变量;
  • 调用一个名为isbn的函数从一个Sales_item对象中提取ISBN书号;
  • 用输入运算符(>>)和输出运算符(<<)读写Sales_item类型的对象;
  • 用赋值运算符(=) 将一个Sales_item对象的值赋给另一个Sales_item;
  • 用加法运算符(+)将两个Sales_item对象相加。两个对象必须表示同一本书(相同的ISBN)。加法的结果是一个新的Sales_item对象,其ISBN与两个运算对象相同,而总销售额和售出册数则是两个运算对象的对应值之和。
  • 使用复合赋值运算符(+=)将一个Sales_item对象加到另一个对象上;
#include<iostream>
#include"Sales_item.h"
using namespace std;
int main()
{
	Sales_item book;
	cin >> book;
	cout << book << endl;
	return 0;
}
#pragma once
#ifndef SALESITEM_H
#define SALESITEM_H
#include <iostream>
#include <string>

class Sales_item
{
public:
	Sales_item(const std::string& book) :isbn(book), units_sold(0), revenue(0.0) {}
	Sales_item(std::istream& is) { is >> *this; }
	friend std::istream& operator>>(std::istream&, Sales_item&);
	friend std::ostream& operator<<(std::ostream&, const Sales_item&);
public:
	Sales_item& operator+=(const Sales_item&);
public:
	double avg_price() const;
	bool same_isbn(const Sales_item& rhs)const
	{
		return isbn == rhs.isbn;
	}
	Sales_item() :units_sold(0), revenue(0.0) {}
public:
	std::string isbn;
	unsigned units_sold;
	double revenue;
};

using std::istream;
using std::ostream;
Sales_item operator+(const Sales_item&, const Sales_item&);
inline bool operator==(const Sales_item& lhs, const Sales_item& rhs)
{
	return lhs.units_sold == rhs.units_sold && lhs.revenue == rhs.revenue && lhs.same_isbn(rhs);
}
inline bool operator!=(const Sales_item& lhs, const Sales_item& rhs)
{
	return !(lhs == rhs);
}

inline Sales_item& Sales_item::operator +=(const Sales_item& rhs)
{
	units_sold += rhs.units_sold;
	revenue += rhs.revenue;
	return *this;
}
inline Sales_item operator+(const Sales_item& lhs, const Sales_item& rhs)
{
	Sales_item ret(lhs);
	ret += rhs;
	return ret;
}
inline istream& operator>>(istream& in, Sales_item& s)
{
	double price;
	in >> s.isbn >> s.units_sold >> price;
	if (in)
		s.revenue = s.units_sold * price;
	else
		s = Sales_item();
	return in;
}
inline ostream& operator<<(ostream& out, const Sales_item& s)
{
	out << s.isbn << "\t" << s.units_sold << "\t" << s.revenue << "\t" << s.avg_price();
	return out;
}
inline double Sales_item::avg_price() const
{
	if (units_sold)
		return revenue / units_sold;
	else
		return 0;
}
#endif

注释:

  • 使用来自非标准库的头文件时应使用("")
  • 在创建过工程时应,应该添加一个Sales_item.h开头的头文件,并且在cpp文件中包含此文件。

#include<iostream>
#include"Sales_item.h"
using namespace std;
int main()
{
	Sales_item item1, item2;
	cin >> item1 >> item2;
	if (item1.isbn == item2.isbn)//这里是定义公共成员变量:string isbn;
	{
		cout << item1 + item2 << endl;
		return 0;
	}
	else
	{
		cerr << "Data must refer to same ISBN" << endl;
		return -1;
	}
}

注释:

  • 书本上关于成员函数说法有误,Sales_item.h头文件中包含的是string类型的公共成员变量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 (cin >> total)
	{
		Sales_item trans;
		while (cin >> trans)
		{
			if (total.isbn == trans.isbn)
			{
				total += trans;
			}
			else
			{
				cout << total << endl;
				total = trans;
			}
			cout << total << endl;
		}
	}
	else
	{
		cerr << "No data?!" << endl;
		return -1;
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值