一、程序源文件命名约定
无论你使用命令行界面或者IDE,大多数编译器都要求程序源码存储在一个或多个文件中。程序文件通常被称为源文件(source file)。在大多数系统中,源文件的名字以一个后缀为结尾,后缀是由一个句点后接-一个或多个字符组成的。后缀告诉系统这个文件是一个C++程序。不同编译器使用不同的后缀命名约定,最常见的包括. cc、.cxx、.cpp、.cp及.C。
二、初识输入输出
本书中的很多示例都使用了iostream 库。iostream 库包含两个基础类型istream和ostream,分别表示输入流和输出流。一个流就是一个字符序列,是从IO设备读出或写入IO设备的。术语“流" (stream)想要表达的是,随着时间的推移,字符是顺序生成或消耗的。
#include < iostream > // 头文件
int main()
{
std::cout < < "Enter two numbers : " < < std::endl;
int v1 = 0, v2 = 0;
std::cin > > v1 > > v2 ;
std::cout< < "The sum of " < < v1 < < " and " < < v2 < < " is " < < v1 + v2 < < std::endl;
return 0;
}
这个程序开始时在用户屏幕打印
Enter two numbers :
然后等待用户输入。如果用户键入
6 8
然后键入一个回车,则程序产生如下输出:
The sum of 6 and 8 is 14
1、向流写入数据
main 的函数体的第一条语句执行了一个表达式(expression)。在C++中,一个表达式产生一个计算结果,它由一个或多个运算对象和(通常是) 一个运算符组成。这条语句中的表达式使用了输出运算符(<<)在标准输出上打印消息:
std::cout < < "Enter two numbers : " < < std::endl;
<< 运算符接受两个运算对象:左侧的运算对象必须是一个 ostream对象,右侧的运算对象是要打印的值。此运算符将给定的值写到给定的ostream对象中。输出运算符的计算结果就是其左侧运算对象。即,计算结果就是我们写入给定值的那个ostream对象。我们的输出语句使用了两次<<运算符。因为此运算符返回其左侧的运算对象,因此第一个运算符的结果成为了第二个运算符的左侧运算对象。这样,我们就可以将输出请求连接起来。
因此,我们的表达式等价于;
(std::cout << "Enter two numbers:") << std::endl;
等价于:
std: :cout << "Enter two numbers:";
std: :cout << std: :endl;
第一个输出运算符给用户打印一条消息。这个消息是一个字符串字面值常量(string literal),是用一对双引号包围的字符序列。在双引号之间的文本被打印到标准输出。
第二个运算符打印endl,这是一个被称为操纵符(manipulator)的特殊值。写入endl的效果是结束当前行,并将与设备关联的缓冲区( buffer)中的内容刷到设备中。缓冲刷新操作可以保证到目前为止程序所产生的所有输出都真正写入输出流中,而不是仅停留在内存中等待写入流。
2、使用标准库中的名字
细心的读者可能会注意到这个程序使用了std: :cout和std: :endl。前缀std: :指出名字cout和endl是定义在名为std的命名空间(namespace)中的。标准库定义的所有名字都在命名空间std中。通过命名空间使用标准库有一个副作用:当使用标准库中的一个名字时,必须显式说明我们想使用来自命名空间std中的名字。例如,需要写出std: :cout,通过使用作用域运算符( :: )来指出我们想使用定义在命名空间std中的名字cout。将给出一个更简单的访问标准库中名字的方法。
3、从流读取数据
在提示用户输入数据之后,接下来我们希望读入用户的输入。
std: :cin >> v1 >> v2;
它读入输入数据。输入运算符(>>)与输出运算符类似,它接受一个istream作为其左侧运算对象,接受一个对象作为其右侧运算对象。它从给定的istream 读入数据,并存入给定对象中。与输出运算符类似,输入运算符返回其左侧运算对象作为其计算结果。
因此,此表达式等价于(std: :cin >> v1) >> v2;
等价于:
std::cin >> v1;
std::cin>>v2;
三、注释简介
// 正确
/* 正确 */
/* 正确
*/
/*
★注释对/* */不 能嵌套。
★
“不能嵌套”几个字会被认为是源码,
★像剩余程序一样处理
*/
#include < iostream >
int main()
{
std ::cout < < "/*";
std ::cout < < "*/";
std ::cout < < /* "*/" */";
std ::cout < < /*"*/"/*"/*" */;
return 0;
}
四、控制流
语句一般是顺序执行的:语句块的第一条语句首先执行, 然后是第二条语句,依此类推。但程序设计语言提供了多种不同的控制流语句,允许我们写出更为复杂的执行路径。
1、while语句
C语言学习进阶~总贴
2、for语句
C语言学习进阶~总贴
3、读取数量不定的输人数据
在某种情况下,我们预先不知道要对多少个数求和,这就需要不断读取数据直至没有新的输入为止:
#include < iostream >
int main()
{
int sum = 0, value = 0;
std::cout < < "Enter " < < std::endl;
while (std::cin > > value) //读取数据直到遇到文件尾,计算所有读入的值的和
sum += value; //等价于sum=sum+value
std::cout < < "Sum is : " < < sum < < std::endl;
return 0;
}
如果我们输入.
3 4 5 6 7 8
则程序会输出
Sum is : 33
因此,我们的while 循环会一直执行 直至遇到文件结束符(或输入错误)。while循环体使用复合赋值运算符将当前值加到sum上。一旦条件失败,while循环将会结束。将执行下一条语句,打印sum的值和一个endl。
从键盘输入文件结束符
当从键盘向程序输入数据时,对于如何指出文件结束,不同操作系统有不同的约定。在Windows系统中,输入文件结束符的方法是敲Ctrl+Z (按住Ctrl 键的同时按Z键),然后按Enter或Return键。在UNIX系统中,包括MacOSX系统中,文件结束符输入是用Ctrl+D。
4、if 语句
与大多数语言一样,C++也提供了if语句来支持条件执行。我们可以用if语句写一个程序,来统计在输入中每个值连续出现了多少次:
#include < iostream >
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;
}
5、类简介
在C++中,我们通过定义一个类(class) 来定义自己的数据结构。一个类定义了一个类型,以及与其关联的一组操作。类机制是C++最重要的特性之一。实际上,C++最初的一个设计焦点就是能定义使用上像内置类型一样自然的类类型(class type)。
为了使用类,我们需要了解三件事情:
- 类名是什么?
- 它是在哪里定义的?
- 它支持什么操作?
每个类实际上都定义了一个新的类型,其类型名就是类名。因此,我们的Sales_ item类定义了一个名为Sales_ item的类型。与内置类型一样,我们可以定义类类型的变量。当我们写下如下语句:
Sales item item;
是想表达item是一个Sales_ item 类型的对象。
(1)读写Sales_ item
#include < iostream >
#include "Sales_item.h"
int main()
{
Sales_item book;
//读入ISBN号、售出的册数以及销售价格.
std:: cin > > book;
//写入ISBN、 售出的册数、总销售额和平均价格
std:: cout < < book < < std:: endl;
return 0;
}
如果输入:
0-201-70353-X 4 24.99
则输出为:
0-201-70353-x 4 99.96 24.99
(2)Sales_ item对象的加法
#include < iostream >
#include "Sales_ item.h"
int main()
{
Sales_item item1,item2;
std:: cin > > iteml > > item2;
//读取一对交易记录
std:: cout < < item1 + item2 < < std :: endl;
//打印它们的和
return 0;
}
如果输入如下内容:
0-201-78345-X 3 20. 00
0-201-78345-x 2 25.00
则输出为:
0-201-78345-X 5 110 22
(3)初识成员函数
将两个Sales_item对象相加的程序首先应该检查两个对象是否具有相同的ISBN。
方法如下:
#include < iostream >
#include "Sales item.h"
int main()
{
Sales_item iteml, item2;
std::cin > > iteml > > item2;
//首先检查item1和item2是否表示相同的书
if (iteml.isbn() == item2.isbn()) {
std::cout < < item1 + item2 < < std::endl;
return 0; // 表示成功
}
else {
std::cerr < < "Data must refer to same ISBN" < < std :: endl;
return -1;
//表示失败
}
}
什么是成员函数?
这个if语句的检测条件 item1. isbn() == item2.isbn()
调用名为isbn的成员函数(member function)。成员函数是定义为类的一部分的函数,有时也被称为方法(method)。我们通常以一个类对象的名义来调用成员函数。
使用点运算符(.)来表达我们需要“名为item1的对象的isbn成员”。点运算符只能用于类类型的对象。其左侧运算对象必须是一个类类型的对象,右侧运算对象必须是该类型的一个成员名,运算结果为右侧运算对象指定的成员。
6、书店程序
我们需要从一个文件中读取销售记录,生成每本书的销售报告,显示售出册数、总销售额和平均售价。我们假定每个ISBN书号的所有销售记录在文件中是聚在一起保存的。
我们的程序会将每个ISBN的所有数据合并起来,存入名为total的变量中。我们使用另一-个名为trans的变量保存读取的每条销售记录。如果trans和total指向相同的ISBN,我们会更新total的值。否则,我们会打印total的值,并将其重置为刚刚读取的数据(trans):
#include < iostream >
#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;
}
#include "sales_item.h"
#ifndef __C__project__Sales_item__
#define __C__project__Sales_item__
#include < stdio.h >
#include < iostream >
#include < string >
class Sales_item {
// these declarations are explained section 7.2.1, p. 270
// and in chapter 14, pages 557, 558, 561
friend std::istream& operator > >(std::istream&, Sales_item&);
friend std::ostream& operator< < (std::ostream&, const Sales_item&);
friend bool operator< (const Sales_item&, const Sales_item&);
friend bool
operator==(const Sales_item&, const Sales_item&);
public:
// constructors are explained in section 7.1.4, pages 262 - 265
// default constructor needed to initialize members of built-in type
Sales_item() : units_sold(0), revenue(0.0) { }
Sales_item(const std::string &book) :
bookNo(book), units_sold(0), revenue(0.0) { }
Sales_item(std::istream &is) { is > > *this; }
public:
// operations on Sales_item objects
// member binary operator: left-hand operand bound to implicit this pointer
Sales_item& operator+=(const Sales_item&);
// operations on Sales_item objects
std::string isbn() const { return bookNo; }
double avg_price() const;
// private members as before
private:
std::string bookNo; // implicitly initialized to the empty string
unsigned units_sold;
double revenue;
};
// used in chapter 10
inline
bool compareIsbn(const Sales_item &lhs, const Sales_item &rhs)
{
return lhs.isbn() == rhs.isbn();
}
// nonmember binary operator: must declare a parameter for each operand
Sales_item operator+(const Sales_item&, const Sales_item&);
inline bool
operator==(const Sales_item &lhs, const Sales_item &rhs)
{
// must be made a friend of Sales_item
return lhs.units_sold == rhs.units_sold &&
lhs.revenue == rhs.revenue &&
lhs.isbn() == rhs.isbn();
}
inline bool
operator!=(const Sales_item &lhs, const Sales_item &rhs)
{
return !(lhs == rhs); // != defined in terms of operator==
}
// assumes that both objects refer to the same ISBN
Sales_item& Sales_item::operator+=(const Sales_item& rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
// assumes that both objects refer to the same ISBN
Sales_item
operator+(const Sales_item& lhs, const Sales_item& rhs)
{
Sales_item ret(lhs); // copy (|lhs|) into a local object that we'll return
ret += rhs; // add in the contents of (|rhs|)
return ret; // return (|ret|) by value
}
std::istream&
operator > >(std::istream& in, Sales_item& s)
{
double price;
in > > s.bookNo > > s.units_sold > > price;
// check that the inputs succeeded
if (in)
s.revenue = s.units_sold * price;
else
s = Sales_item(); // input failed: reset object to default state
return in;
}
std::ostream&
operator< < (std::ostream& out, const Sales_item& s)
{
out < < s.isbn() < < " " < < s.units_sold < < " "
< < s.revenue < < " " < < s.avg_price();
return out;
}
double Sales_item::avg_price() const
{
if (units_sold)
return revenue / units_sold;
else
return 0;
}
#endif /* defined(__C__project__Sales_item__) */
五、术语表
- 参数(实参,argument)向函数传递的值。
- 赋值( assignment)抹去一个对象的当前值,用一个新值取代之。
- 程序块(block) 零条或多条语句的序列,用花括号包围。
- 缓冲区(buffer)一个存储区域,用于保存数据。I0设施通常将输入(或输出)数据保存在一个缓冲区中,读写缓冲区的动作与程序中的动作是无关的。我们可以显式地刷新输出缓冲,以便强制将缓冲区中的数据写入输出设备。默认情况下,读cin会刷新cout;程序非正常终止时也会刷新cout.
- 内置类型(built-in type)由语言定义的类型,如int。
- Cerr一个ostream对象,关联到标准错误,通常写入到与标准输出相同的设备。默认情况下,写到cerr的数据是不缓冲的。cerr通常用于输出错误信息或其他不属.于程序正常逻辑的输出内容。
- 字符串字面值常量( character stringliteral)术语string literal的另-种叫法。cin一个istream对象,用来从标准输入读取数据。
- 类(class)一种用于定义自己的数据结构及其相关操作的机制。类是C++中最基本的特性之一。标准库类型中,如istream和ostream都是类。
- 类类型(class type)类定义的类型。类名即为类型名。
- clog一个ostream对象,关联到标准错误。默认情况下,写到clog的数据是被缓冲的。clog通常用于报告程序的执行信息,存入一个日志文件中。
- 注释(comment)被编译器忽略的程序文本。C++有两种类型的注释:单行注释和界定符对注释。单行注释以//开始,从//到行尾的所有内容都是注释。界定符对注释以/ 开始,其后的所有内容都是注释,直至遇到 /为止。
- 条件(condition)求值结果为真或假的表达式。通常用值0表示假,用非零值表示真。
- cout一个ostream对象,用于将数据写入标准输出。通常用于程序的正常输出内容。
- 花括号(curly brace)花括号用于划定程序块边界。左花括号({)为程序块开始,右花括号(})为结束。
- 数据结构(data structure) 数据及其.上所允许的操作的一种 逻辑组合。
- 编辑-编译-调试( edit-compile-debug)使程序能正确执行的开发过程。
- 文件结束符(end-of-file) 系 统特定的标识,指出文件中无更多数据了。表达式(expression) 最小的计算单元。一个表达式包含一个或多个运算对象,通常还包含一个或多个运算符。表达式求值会产生一个结果。例如,假设i和j是int对象,则i+j是一个表达式,它产生两个int值的和。
- for语句( for statement)迭代语句,提供重复执行能力。通常用来将一个计算反复执行指定次数。
- 函数(function)具名的计算单元。
- 函数体(function body)语句块,定义了函数所执行的动作。
- 函数名( function name)函数 为人所知的名字,也用来进行函数调用。
- 头文件(header) 使类或其他名字的定义可被多个程序使用的一种机制。程序通过#include指令使用头文件。
- if语句(if statement) 根据一 个特定条件的值进行条件执行的语句。如果条件为真,执行if语句体。否则,执行else语句体(如果存在的话)。
- 初始化(initialize) 在一个对象创建的时候赋予它一个值。
- iostream头文件,提供了面向流的输入输出的标准库类型。
- istream提供了面向流的输入的库类型。
- 库类型(library type)标准库定义的类型,如istream.
- main操作系统执行一个C++程序时所调用的函数。每个程序必须有且只有一个命名为main的函数。
- 操纵符(manipulator)对象,如std:end1,在读写流的时候用来“操纵”流本身。
- 成员函数( member function)类定义的操作。通常通过调用成员函数来操作特定对象。
- 方法(method)成员函数的同义术语。
- 命名空间( namespace)将库定义的名字放在一个单一位置的机制。命名空间可以帮助避免不经意的名字冲突。C++标准库定义的名字在命名空间std中。
- ostream标准库类型,提供面向流的输出。
- 形参列表( parameter list) 函数定义的部分,指出调用函数时可以使用什么样的实参,可能为空列表。
- 返回类型(return type)函数返回值的类型。
- 源文件( source file )包含C++程序的文件。
- 标准错误(standard error)输出流,用于报告错误。标准输出和标准错误通常关联到程序执行所在的窗口。
- 标准输入(standard input)输入流,通常与程序执行所在窗口相关联。
- 标准库(standard library) 一个类型和函数的集合,每个C++编译器都必须支持。标准库提供了支持I0操作的类型。C++程序员倾向于用“库”指代整个标准库,还倾向于用库类型表示标准库的特定部分,例如用“iostream库”表示标准库中定义I0类的部分。
- 标准输出(standard output) 输出流,通常与程序执行所在窗口相关联。
- 语句(statement) 程序的一部分,指定了当程序执行时进行什么动作。一个表达式接一个分号就是一条语句;其他类型的语旬包括语句块、if语旬、for语句和while语句,所有这些语句内都包含其他语句。
- std标准库所使用的命名空间。std: :cout表示我们要使用定义在命名空间std中的名字cout.
- 字符串常量(string literal) 零或多个字符组成的序列,用双引号包围("a stringliteral")。
- 未初始化的变量( uninitialized variable )未赋予初值的变量。类类型的变量如果未指定初值,则按类定义指定的方式进行初始化。定义在函数内部的内置类型变量默认是不初始化的,除非有显式的初始化语句。试图使用一个未初始化变量的值是错误的。未初始化变量是bug的常见成因。
- 变量(variable)具名对象。:
- while语句( while statement)迭代语句,提供重复执行直至一个特定条件为假的机制。循环体会执行零次或多次,依赖于循环条件求值结果。
- ()运算符() operator)调用运算符。跟随在函数名之后的一对括号“()”,起到调用函数的效果。传递给函数的实参放置在括号内。
- ++运算符(++ operator)递增运算符。将运算对象的值加1,++i等价于i=i+1。
- +=运算符(+= operator)复合赋值运算符,将右侧运算对象加到左侧运算对象上;a+=b等价于a=a+b.
- .运算符(. operator) 点运算符。左侧运算对象必须是一个类类型对象,右侧运算对象必须是此对象的一个成员的名字。运算结果即为该对象的这个成员。
- ::运算符(:: operator)作用域运算符。其用处之一是访问命名空间中的名字。例如,std::cout表示命名空间std中的名字cout。
- =运算符(= operator) 将右侧运算对象的值赋予左侧运算对象所表示的对象。
- --运算符(-- operator)递减运算符。将运算对象的值减1,--i等价于i=i-1。
- <<运算符(<< operator)输出运算符。将右侧运算对象的值写到左侧运算对象表示的输出流: (cout<< "hi"表示将hi写到标准输出。输出运算符可以连接: cout <<"hi" << "bye"表示将输出hibye.
运算符(>> operator)输入运算符。从左侧运算对象所指定的输入流读取数据,存入右侧运算对象中: cin>> i表示从标准输入读取下一个值,存入i中。输入运算符可以连接: cin>> i>> j表示先读取一个值存入i,再读取一个值存入j。
- #include头文件包含指令,使头文件中代码可被程序使用。
- ==运算符(== operator)相等运算符。检测左侧运算对象是否等于右侧运算对象。
- !=运算符(!= operator)不等运算符。检测左侧运算对象是否不等于右侧运算对象。
- <=运算符(<= operator)小于等于运算符。检测左侧运算对象是否小于等于右侧运算对象。
- <运算符(< operator)小于运算符。检测左侧运算对象是否小于右侧运算对象。
=运算符(>= operator)大于等于运算符。检测左侧运算对象是否大于等于右侧运算对象。
运算符(> operator)大于运算符。检测左侧运算对象是否大于右侧运算对象。
评论
查看更多