c++ primer plus 第六版 第九章重点内容总结以及 编程题答案

1.单独编译

程序可以分成头文件(包含结构声明和使用这些结构的函数的原型),源代码文件(包含与结构有关的函数的代码),源代码文件(包含调用与结构相关的函数代码)。头文件中常包含函数原型,使用#define或const定义的符号常量,结构声明,类声明,模板声明,内联函数。在使用自己定义的头文件时使用#include“ haha.h”,如果为<>时,c++将在存储标准头文件的主机系统的文件系统中查找,在双引号中首先查找当前的工作目录或源代码目录。

 

避免多次包含同一个头文件:基于预处理器编译指令#infdef(if not defined),仅当以前没有使用预处理器编译指令#define定义名称COORDIN_H的时候,才处理#infdef和#endif之间的语句。

#ifndef COORDIN_H

#define COORDIN_H

#endif

当编译器首次遇到该文件时,名称COOEDIN_H未定义,编译器才查看#ifndef和#endif之间的内容,并读取定义COORDIN_H的一行,如果在同一个文件中遇到其他包含coordin.h的代码,将跳到endif后面的一行上。不过该方案只能让它忽略除第一次包含之外的所有内容。

 

2.存储持续性、作用域和链接性

C++使用三种不同方案存储数据,这些方案的区别在于数据保留在内存中的时间。

 

自定存储持续性:在函数定义中声明的变量(包括函数参数)存储持续性是自动的。

 

静态存储持续性:在函数外定义的变量和使用关键字static定义的变量的存持续性都为静态,在程序整个运行过程中都存在。

 

线程存储持续性:多核处理器的cpu可以同时处理多个执行任务。这让程序能够将计算放在可并行处理的不同线程之中。如果变量使用关键字thread_local声明的,那么其生命周期与所属线程一样长。

 

动态存储持续性:用new运算符分配的内存将一直存在,直到delete运算符将其释放或程序结束为止。这种内存的存储持续性为动态,也叫自由存储或者堆。

 

链接性为外部的名称可在文件间共享,链接性为内部的名称只能由一个文件内的函数共享。自动变量的名称没有链接性,因此它们不能共享。

 

自动变量和栈:因为自动变量的数目随函数的开始和结束增减,为了实现对自动变量的管理,常常留出一段内存视为栈。新数据被象征性地放在原有数据的上面(在相邻内存单元中而不是同一个内存单元中),当程序使用完后将其从栈删除。程序使用两个指针来追踪栈,一个指向栈底(栈的开始位置),一个指向栈顶(下一个可用内存单元)。当函数被调用时,其自动变量将被加入栈中,栈顶指针指向变量后面的下一个可用的内存单元。函数结束时栈顶指针被重置为函数被调用前的值,从而释放新变量使用的内存。

栈是LIFO后进先出的,调用函数时将实参压入栈底(起始位置)中,栈顶指针指向下一个内存单元。函数开始执行后,将栈中的实参值和形参关联起来,函数结束后栈顶恢复到原来的位置。

 

C++为静态存储持续变量提供了三种链接性:外部链接性(可在其他文件中访问),内部链接性(只能在当前文件中访问)和无链接性(只能在当前函数或者代码块中访问)。这三种链接性在整个程序执行期间都是存在的,由于静态变量的数目在程序运行期间是不变的,编译器将分配固定的内存块来存储所有的静态变量。

int global=1000;//外部链接性,别的文件可以使用

static int one_file=50;//内部链接性,文件内访问

int main(){…}

void funct1(int n)

{

   Static int count=0;//无链接性(当前函数或者代码块中访问),与自动变量llama的不同是,即使funct1不执行,count也留在内存中。

   Int llama=0;

}

Void funct2(int q){…}
即创建链接性为外部的静态持续变量必须在代码块的外面声明它,创建链接性为内部的静态持续变量,必须在代码块的外面声明它并且使用const限定符,创建没有链接性的静态持续变量必须在代码块内声明它。并使用static限定符。注意,未被初始化的静态变量的所有位都被设置成0,这种变量被称为零初始化。

 

静态变量的初始化:零初始化是必须的并且与常量表达式初始化统称为静态初始化,也可以进行动态初始化,即在编译后进行初始化,如右值调用了某个函数,注意调用sizeof运算符使用常量表达式初始化。

 

静态持续性、外部链接性:

外部变量(链接性是外部的变量,也叫全局变量),它们的存储持续性为静态,作用于是整个文件。注意定义给变量分配空间,声明不给变量分配存储空间,因为它引用已有的变量。如double up;是定义并且已经赋值0,使用extern int blem;是声明;extern char gz=‘z’;是定义,虽然用了extern但是初始化了。即使用extern声明变量且不进行初始化时才是声明。

 

单定义规则(变量只能有一次定义,与赋值区分开):如果要在多个文件中使用外部变量,只需要在一个文件中包含其定义,但是在使用其他变量的所有文件中,使用extern进行声明。::warming;使用域作用符表示使用全局变量。

 

静态持续性,内部链接性:

如果一个文件中定义了外部变量,另一个文件意图定义一个相同名称的内部变量,那么应该使用static 关键字来说明是内部链接性。

 

无链接性的局部变量:,将static限定符用于在代码块中定义的变量,即在改代码块不活动的时候也存在。因此在两次函数调用之间,静态局部变量的值将保持不变。程序只初始化一次静态局部变量。

3.说明符和限定符

volatile关键字表明,假设编译器发现程序在几条语句中两次使用了某个变量,则编译器可能不是查找这个值两次而是将这个值缓存到寄存器里。Volatile关键字相当于不要进行这种优化。

 

Mutable:将其使用在结构或者类内的变量可以实现,即使结构或者类变量为const,其某个成员也可以被修改。

 

Const:注意在c++看来,默认情况下全局变量的链接性为外部的,但const全局变量的链接性为内部的。即全局const定义就像使用了static说明符一样。但是可以使用extern关键字覆盖默认的内部链接性。extern const int states=50;必须在所有使用该常量的文件中使用extern关键字来声明它。另外注意,单个const在多个文件中共享,只有一个文件可以对其进行初始化。

 

函数和链接性:
所有函数的存储持续性都自动为静态的,在整个程序执行期间存在。默认函数具有外部链接性可在文件之间共享。可在函数原型中使用extern指出函数是在另一个文件中定义的。也可以使用static将函数设置为内部使之只能在一个文件中使用。必须同时在函数原型和函数定义中都使用static。单定义规则也适用于非内联函数。C++执行名称修饰,名称名称矫正对重载函数生成不同的符号名称(因为c++允许重名函数)。

extern “C” void spiff(int);//使用C链接性

extern “C++” void spiff(int);//显示使用c++链接

extern void spaff(int);//隐式使用c++链接

 

动态分配:

动态内存由运算符new和delete控制,而不是由作用域和链接性规则控制。因此允许在一个函数中分配动态内存,在另一个函数中释放。通常编译器使用三块独立的内存:一块用于静态变量,一块用于自动变量,一块用于动态存储。虽然存储方案概念不适用于动态内存,但适用于用来跟踪动态内存的自动和静态指针变量。如:

float *p_fees=new float[20];由new分配的内存一直保留在内存中,直到使用delete释放。但当包含该语句的代码块执行完时,p_fees指针将消失。如果另一个函数还要使用这80个字节的内容,那么必须将其地址传递或者返回给函数。若将p_fees声明为外部的则文件中位于该声明后后面的所有函数都可以使用它。在另一个文件中extern float *p_fees;声明则可以使用该指针。

 

New运算符初始化:

基本类型: int *pi=new int (6); double * pd=new double (99.99);

初始化常规结构或者数组需使用大括号的列表初始化(支持c++11):

Struct where {double x; double y; double z};

Where *one =new where {2.5,5.3,7.2};

Int *ar=new int[4] {2,4,6,7};

New失败时,引发std::bad_alloc异常。

 

New:运算符、函数和替换函数

Void *operator new(std::size_t);

Void *operator new[](std::size_t);

这些被称为分配函数位于全局名称空间中。也有由delete和delete[]调用的释放函数。

Void operator delete(void *);

Void operator delete[](void *);

 

定位new运算符:new还有一种变体被称为定位new运算符,用以指定要使用的位置。需要#include<new>。此时变量后面可以有【】也可以没有。如char buffer1[50];char *p1=new chaff();将结构放在堆中。Char *p2=new (buffer1) chaff();将结构放在buffer静态存储区中。

假设p1是double 指针,如果使用定位new运算符时候,而buffer是char数组,那么需要

(void *)buffer强制转换。注意定位new运算符使用传递给它的地址,它不跟踪哪些内存单元已经被使用,也不查找未使用的内存块,所以如果不想覆盖旧数据,在下次写入的时候应该使用偏移量来申请新的内存:pd2=new (buffer +N*sizeof(double)) double[N];

 

Delete运算符只能用于这样的指针:指向常规new运算符分配的堆内存。即此时定位new分配在静态内存中,所以不能用delete删除。

 

4.名称空间

声明区域:可在其中进行声明的区域。

潜在作用域:变脸从声明点开始到其声明区域的结尾。

作用域:变量对程序而言可见的范围被称为作用域。

 

新的名称空间:通过定义一种新的声明区域来创建命名的名称空间。使用关键字namespace

Namespace jack

{

   Double pail;

   Void fetch();

   Struct hill();

}

名称空间可以是全局的(外部的),也可以位于另一个名称空间中,但不能位于代码块中。可以在该文件或者另外的文件中使用jack的名称空间为fetch的代码。使用域作用夫::,如

Jack::pail叫限定的名称。

 

注意:假设名称空间和声明区域定义了相同的名称,如果试图使用using声明将名称空间的名称导入该声明区域,则这两个名称将发生冲突而导致错误。如果使用using编译指令将该名称空间的名称导入该声明区域,则局部版本将隐藏名称空间的版本。

Char fetch;

Int main()

{

   Using namespace jack;

   Double fetch; //此时fetch就是局部版本的fetch。

}

Int main()

{

   Using jack::fetch;

   Double fetch;//错误,此时已经有fetch的定义了。

}

 

名称空间其他特性:

Namespace elements

{

   Namespace fire

   {

   Int flame;

}

Float water;

}

此时flame是using namespace elements::flame;也可以在名称空间中声明和编译其他名称空间的名称。Using编译指令是可以传递的,A>B,B>C,那么A>C;即会导入一个名称空间以及其包含的名称空间。也可以给名称空间创建别名,namewpace mvft=my_very_favorate_things; 未命名的名称空间相当于static变量,相当于链接性为内部的静态变量。

 

在做多文件工程项目时,头文件中声明名称空间,常量、结构定义和函数原型都可以加入其中。一个源文件用来完成位于名称空间中的函数定义,且必须在其对应的名称空间中定义。还需要一个源文件代码,使用这些函数、结构和函数原型。

1.单独编译

程序可以分成头文件(包含结构声明和使用这些结构的函数的原型),源代码文件(包含与结构有关的函数的代码),源代码文件(包含调用与结构相关的函数代码)。头文件中常包含函数原型,使用#define或const定义的符号常量,结构声明,类声明,模板声明,内联函数。在使用自己定义的头文件时使用#include“ haha.h”,如果为<>时,c++将在存储标准头文件的主机系统的文件系统中查找,在双引号中首先查找当前的工作目录或源代码目录。

 

避免多次包含同一个头文件:基于预处理器编译指令#infdef(if not defined),仅当以前没有使用预处理器编译指令#define定义名称COORDIN_H的时候,才处理#infdef和#endif之间的语句。

#ifndef COORDIN_H

#define COORDIN_H

#endif

当编译器首次遇到该文件时,名称COOEDIN_H未定义,编译器才查看#ifndef和#endif之间的内容,并读取定义COORDIN_H的一行,如果在同一个文件中遇到其他包含coordin.h的代码,将跳到endif后面的一行上。不过该方案只能让它忽略除第一次包含之外的所有内容。

 

2.存储持续性、作用域和链接性

C++使用三种不同方案存储数据,这些方案的区别在于数据保留在内存中的时间。

 

自定存储持续性:在函数定义中声明的变量(包括函数参数)存储持续性是自动的。

 

静态存储持续性:在函数外定义的变量和使用关键字static定义的变量的存持续性都为静态,在程序整个运行过程中都存在。

 

线程存储持续性:多核处理器的cpu可以同时处理多个执行任务。这让程序能够将计算放在可并行处理的不同线程之中。如果变量使用关键字thread_local声明的,那么其生命周期与所属线程一样长。

 

动态存储持续性:用new运算符分配的内存将一直存在,直到delete运算符将其释放或程序结束为止。这种内存的存储持续性为动态,也叫自由存储或者堆。

 

链接性为外部的名称可在文件间共享,链接性为内部的名称只能由一个文件内的函数共享。自动变量的名称没有链接性,因此它们不能共享。

 

自动变量和栈:因为自动变量的数目随函数的开始和结束增减,为了实现对自动变量的管理,常常留出一段内存视为栈。新数据被象征性地放在原有数据的上面(在相邻内存单元中而不是同一个内存单元中),当程序使用完后将其从栈删除。程序使用两个指针来追踪栈,一个指向栈底(栈的开始位置),一个指向栈顶(下一个可用内存单元)。当函数被调用时,其自动变量将被加入栈中,栈顶指针指向变量后面的下一个可用的内存单元。函数结束时栈顶指针被重置为函数被调用前的值,从而释放新变量使用的内存。

栈是LIFO后进先出的,调用函数时将实参压入栈底(起始位置)中,栈顶指针指向下一个内存单元。函数开始执行后,将栈中的实参值和形参关联起来,函数结束后栈顶恢复到原来的位置。

 

C++为静态存储持续变量提供了三种链接性:外部链接性(可在其他文件中访问),内部链接性(只能在当前文件中访问)和无链接性(只能在当前函数或者代码块中访问)。这三种链接性在整个程序执行期间都是存在的,由于静态变量的数目在程序运行期间是不变的,编译器将分配固定的内存块来存储所有的静态变量。

int global=1000;//外部链接性,别的文件可以使用

static int one_file=50;//内部链接性,文件内访问

int main(){…}

void funct1(int n)

{

   Static int count=0;//无链接性(当前函数或者代码块中访问),与自动变量llama的不同是,即使funct1不执行,count也留在内存中。

   Int llama=0;

}

Void funct2(int q){…}
即创建链接性为外部的静态持续变量必须在代码块的外面声明它,创建链接性为内部的静态持续变量,必须在代码块的外面声明它并且使用const限定符,创建没有链接性的静态持续变量必须在代码块内声明它。并使用static限定符。注意,未被初始化的静态变量的所有位都被设置成0,这种变量被称为零初始化。

 

静态变量的初始化:零初始化是必须的并且与常量表达式初始化统称为静态初始化,也可以进行动态初始化,即在编译后进行初始化,如右值调用了某个函数,注意调用sizeof运算符使用常量表达式初始化。

 

静态持续性、外部链接性:

外部变量(链接性是外部的变量,也叫全局变量),它们的存储持续性为静态,作用于是整个文件。注意定义给变量分配空间,声明不给变量分配存储空间,因为它引用已有的变量。如double up;是定义并且已经赋值0,使用extern int blem;是声明;extern char gz=‘z’;是定义,虽然用了extern但是初始化了。即使用extern声明变量且不进行初始化时才是声明。

 

单定义规则(变量只能有一次定义,与赋值区分开):如果要在多个文件中使用外部变量,只需要在一个文件中包含其定义,但是在使用其他变量的所有文件中,使用extern进行声明。::warming;使用域作用符表示使用全局变量。

 

静态持续性,内部链接性:

如果一个文件中定义了外部变量,另一个文件意图定义一个相同名称的内部变量,那么应该使用static 关键字来说明是内部链接性。

 

无链接性的局部变量:,将static限定符用于在代码块中定义的变量,即在改代码块不活动的时候也存在。因此在两次函数调用之间,静态局部变量的值将保持不变。程序只初始化一次静态局部变量。

3.说明符和限定符

volatile关键字表明,假设编译器发现程序在几条语句中两次使用了某个变量,则编译器可能不是查找这个值两次而是将这个值缓存到寄存器里。Volatile关键字相当于不要进行这种优化。

 

Mutable:将其使用在结构或者类内的变量可以实现,即使结构或者类变量为const,其某个成员也可以被修改。

 

Const:注意在c++看来,默认情况下全局变量的链接性为外部的,但const全局变量的链接性为内部的。即全局const定义就像使用了static说明符一样。但是可以使用extern关键字覆盖默认的内部链接性。extern const int states=50;必须在所有使用该常量的文件中使用extern关键字来声明它。另外注意,单个const在多个文件中共享,只有一个文件可以对其进行初始化。

 

函数和链接性:
所有函数的存储持续性都自动为静态的,在整个程序执行期间存在。默认函数具有外部链接性可在文件之间共享。可在函数原型中使用extern指出函数是在另一个文件中定义的。也可以使用static将函数设置为内部使之只能在一个文件中使用。必须同时在函数原型和函数定义中都使用static。单定义规则也适用于非内联函数。C++执行名称修饰,名称名称矫正对重载函数生成不同的符号名称(因为c++允许重名函数)。

extern “C” void spiff(int);//使用C链接性

extern “C++” void spiff(int);//显示使用c++链接

extern void spaff(int);//隐式使用c++链接

 

动态分配:

动态内存由运算符new和delete控制,而不是由作用域和链接性规则控制。因此允许在一个函数中分配动态内存,在另一个函数中释放。通常编译器使用三块独立的内存:一块用于静态变量,一块用于自动变量,一块用于动态存储。虽然存储方案概念不适用于动态内存,但适用于用来跟踪动态内存的自动和静态指针变量。如:

float *p_fees=new float[20];由new分配的内存一直保留在内存中,直到使用delete释放。但当包含该语句的代码块执行完时,p_fees指针将消失。如果另一个函数还要使用这80个字节的内容,那么必须将其地址传递或者返回给函数。若将p_fees声明为外部的则文件中位于该声明后后面的所有函数都可以使用它。在另一个文件中extern float *p_fees;声明则可以使用该指针。

 

New运算符初始化:

基本类型: int *pi=new int (6); double * pd=new double (99.99);

初始化常规结构或者数组需使用大括号的列表初始化(支持c++11):

Struct where {double x; double y; double z};

Where *one =new where {2.5,5.3,7.2};

Int *ar=new int[4] {2,4,6,7};

New失败时,引发std::bad_alloc异常。

 

New:运算符、函数和替换函数

Void *operator new(std::size_t);

Void *operator new[](std::size_t);

这些被称为分配函数位于全局名称空间中。也有由delete和delete[]调用的释放函数。

Void operator delete(void *);

Void operator delete[](void *);

 

定位new运算符:new还有一种变体被称为定位new运算符,用以指定要使用的位置。需要#include<new>。此时变量后面可以有【】也可以没有。如char buffer1[50];char *p1=new chaff();将结构放在堆中。Char *p2=new (buffer1) chaff();将结构放在buffer静态存储区中。

假设p1是double 指针,如果使用定位new运算符时候,而buffer是char数组,那么需要

(void *)buffer强制转换。注意定位new运算符使用传递给它的地址,它不跟踪哪些内存单元已经被使用,也不查找未使用的内存块,所以如果不想覆盖旧数据,在下次写入的时候应该使用偏移量来申请新的内存:pd2=new (buffer +N*sizeof(double)) double[N];

 

Delete运算符只能用于这样的指针:指向常规new运算符分配的堆内存。即此时定位new分配在静态内存中,所以不能用delete删除。

 

4.名称空间

声明区域:可在其中进行声明的区域。

潜在作用域:变脸从声明点开始到其声明区域的结尾。

作用域:变量对程序而言可见的范围被称为作用域。

 

新的名称空间:通过定义一种新的声明区域来创建命名的名称空间。使用关键字namespace

Namespace jack

{

   Double pail;

   Void fetch();

   Struct hill();

}

名称空间可以是全局的(外部的),也可以位于另一个名称空间中,但不能位于代码块中。可以在该文件或者另外的文件中使用jack的名称空间为fetch的代码。使用域作用夫::,如

Jack::pail叫限定的名称。

 

注意:假设名称空间和声明区域定义了相同的名称,如果试图使用using声明将名称空间的名称导入该声明区域,则这两个名称将发生冲突而导致错误。如果使用using编译指令将该名称空间的名称导入该声明区域,则局部版本将隐藏名称空间的版本。

Char fetch;

Int main()

{

   Using namespace jack;

   Double fetch; //此时fetch就是局部版本的fetch。

}

Int main()

{

   Using jack::fetch;

   Double fetch;//错误,此时已经有fetch的定义了。

}

 

名称空间其他特性:

Namespace elements

{

   Namespace fire

   {

   Int flame;

}

Float water;

}

此时flame是using namespace elements::flame;也可以在名称空间中声明和编译其他名称空间的名称。Using编译指令是可以传递的,A>B,B>C,那么A>C;即会导入一个名称空间以及其包含的名称空间。也可以给名称空间创建别名,namewpace mvft=my_very_favorate_things; 未命名的名称空间相当于static变量,相当于链接性为内部的静态变量。

 

在做多文件工程项目时,头文件中声明名称空间,常量、结构定义和函数原型都可以加入其中。一个源文件用来完成位于名称空间中的函数定义,且必须在其对应的名称空间中定义。还需要一个源文件代码,使用这些函数、结构和函数原型。

//+++++++++++++++++++++++9_1.hpp++++++++++++++++++++++++++
#include<iostream>
using namespace std;
const int len=40;
const int input=50;
struct golf
{
   char fullname[len];
   int handicap;
};
void setgolf(golf &g,const char *name,int hc);
int setgolf(golf &g);
void handicap(golf &g, int hc);
void showgolf(const golf &g);
//+++++++++++++++++++++++++9_1.cpp+++++++++++++++++++++++++++
#include<iostream>
#include<cstring>
#include"9_1.hpp"
void setgolf(golf &g,const char *name,int hc)
{
   strcpy(g.fullname,name);
   g.handicap=hc;
}

int setgolf(golf &g)
{
   
   char a[len];
   int b;
   int bo=1;
   cout<<"enter your name"<<endl;
   cin.getline(a,len);
   if(strlen(a)==0)
      bo=0;
   //cin.get();
   cout<<"enter your handicao"<<endl;
   cin>>b;
   cin.get();
   strcpy(g.fullname,a);
   g.handicap=b;
   return bo;   
}
void handicap(golf &g,int hc)
{
   g.handicap=hc;
}
void showgolf(const golf &g)
{
   cout<<"your input name is"<<g.fullname<<endl;
   cout<<"your input handicap is "<<g.handicap<<endl;
}
//++++++++++++++++++++++++++9_1_main.cpp++++++++++++++++++++++
#include<iostream>
#include"9_1.hpp"
int main()
{
   golf ann;
   setgolf(ann,"Ann Birdfree",24);
   showgolf(ann);
   golf pt[input];
   for(int i=0;i<input;i++)
   {
      int boo=setgolf(pt[i]);
      if(boo==0)
         break; 
      showgolf(pt[i]);     
   }   
   handicap(ann,20);
   showgolf(ann);
   return 0;
}
//++++++++++++++++++++++++++++9_2.cpp++++++++++++++++++++++++++
#include<iostream>
#include<string>
using std::string;
const int arsize=10;
void strcount(string);
int main()
{
   using namespace std;
   string input;
   cout<<"enter a line\n";
   getline(cin,input);
   while(cin)
   {
     
      if(input=="")
         break;
      strcount(input);
      cout<<"enter nest line"<<endl;
      getline(cin,input);
   }
   cout<<"bye"<<endl;
   return 0;
}

void strcount(string str)
{
   using namespace std;
   static int total=0;
   int count=str.length();
   total+=count;
   cout<<"the string contatins "<<count<<endl;
   cout<<"all are "<<total<<endl;
}
//++++++++++++++++++++++++++9_3.cpp+++++++++++++++++++++++++++
#include<iostream>
#include<new>
#include<cstring>
using namespace std;
const int size =2;
struct chaff
{
   char dross[20];
   int slag;
};
char buffer[1024];
int main()
{
   chaff *p1=new (buffer) chaff[size];
   char *p2=new char[1024];
   chaff *p3=new (p2) chaff[size];
   char input_dross[20];
   int input_slag;
   for(int i=0;i<size;i++)
   {
      cout<<"enter your "<<i<<" information"<<endl;
      cin.getline(input_dross,20);
      strcpy(p1[i].dross,input_dross);
      strcpy(p3[i].dross,input_dross);
      cin>>input_slag;
      cin.get();
      p1[i].slag=input_slag;
      p3[i].slag=input_slag;
      cout<<"p1's information are "<<p1[i].dross<<" "<<p1[i].slag<<endl;
      cout<<"p1's address is "<<&p1[i]<<endl;
      cout<<"p3's infromation are "<<p3[i].dross<<" "<<p3[i].slag<<endl;
      cout<<"p3's address is "<<&p3[i]<<endl;
   }
   
   
}

//+++++++++++++++++++++++++++9_4.hpp+++++++++++++++++++++++++++
#include<iostream>
namespace SALES
{
   const int quarters=4;
   struct sales
   {
      double sale[quarters];
      double average;
      double max;
      double min;
   };
   void setsales(sales &s,const double ar[],int n);
   void setsales(sales &s);
   void showsales(const sales &s);
}
//++++++++++++++++++++++++9_4.cpp+++++++++++++++++++++++++++++++++

#include<iostream>
#include"9_4.hpp"
namespace SALES
{
   using std::cin;
   using std::cout;
   using std::endl;
   void setsales(sales &s,const double ar[],int n)
   {  
      double total=0;
      for(int i=0;i<n&&i<quarters;i++)
      {
         s.sale[i]=ar[i];
         total+=s.sale[i];
         
      }
      double max=s.sale[0];
      double min=s.sale[0];
      for(int j=1;j<n;j++)
      {
         if(max<s.sale[j])
            max=s.sale[j];
         if(min>s.sale[j])
            min=s.sale[j];
         
      }
      s.average=total/n;
      s.max=max;
      s.min=min;
   }
   
   void setsales(sales &s)
   {
      double arr;
      int number;
      cout<<" enter your numbers"<<endl;
      cin>>number;
      cin.get();
      for(int i=0;i<number;i++)
      {
         cout<<"enter your "<<i<<" information"<<endl;
         cin>>arr;
         cin.get();
         s.sale[i]=arr;
         
      }
      double total=0;
      for(int k=0;k<number;k++)
      {
         total+=s.sale[k];
         
      }
      double max=s.sale[0];
      double min=s.sale[0];
      for(int j=1;j<number;j++)
      {
         if(max<s.sale[j])
            max=s.sale[j];
         if(min>s.sale[j])
            min=s.sale[j];
         
      }
      s.average=total/number;
      s.max=max;
      s.min=min;
      
   }
   
   void showsales(const sales &s)
   {
      double number=sizeof(s.sale)/sizeof(double);
      for(int i=0;i<number;i++)
      {
         cout<<s.sale[i]<<endl;
      }
      cout<<s.average<<endl;
      cout<<s.max<<endl;
      cout<<s.min<<endl;
      cout<<"this time done!"<<endl;
      
   }
  
}
//+++++++++++++++++++++++++9_4_main.cpp++++++++++++++++++++++++++++
#include<iostream>
#include"9_4.hpp"
int main()
{
   using SALES::sales;
   sales sa;
   sales sb;
   double a[4]={1,2,3,4};
   setsales(sa,a,4);
   showsales(sa);
   setsales(sb);
   showsales(sb);
   return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值