c程序设计(part1).ppt

上传人:小飞机 文档编号:6503571 上传时间:2023-11-07 格式:PPT 页数:94 大小:840KB
返回 下载 相关 举报
c程序设计(part1).ppt_第1页
第1页 / 共94页
c程序设计(part1).ppt_第2页
第2页 / 共94页
c程序设计(part1).ppt_第3页
第3页 / 共94页
c程序设计(part1).ppt_第4页
第4页 / 共94页
c程序设计(part1).ppt_第5页
第5页 / 共94页
点击查看更多>>
资源描述

《c程序设计(part1).ppt》由会员分享,可在线阅读,更多相关《c程序设计(part1).ppt(94页珍藏版)》请在三一办公上搜索。

1、高级程序设计C+Advanced Programming in C+(part 1),南京大学软件学院郑滔费彝民楼904室,Alan Mathison Turing,John von Neumann,Alonzo Church,Kurt Godel,A man provided with paper,pencil,and rubber,and subject to strict discipline,is in effect a universal Turing Machine.,ENIAC:Electronic Numerical Integrator and Computer EDVAC:

2、Electronic Discrete Variable Automatic Computer,ACM 1947 Association of Computing MachineryTuring Award 1966,Algol 60,BCPL,C,Algol 68,ANSI C,Simula 67,C With Class,C+,FORTRAN 90、PL/1,CLUAda,John Backus,1953,1977,Alan JPerlis,1958,1966,E.W.Dijkstra 1960,1972,C.A.R.Hoare1966,1980,Niklaus Wirth 1966,19

3、94,Donald E.Knuth 1965,1974,Dennis Ritchie Ken Thompson1972,1983,Ole-Johan DahlKristen Nygaard1962,2001,Barbara Liskov 70,2008,背景,1962,Kristen Nygaard(KN),initiated a projectSimulation LanguageUNIVAC,选择,FORTRAN or ALGOL60?,the block structuregood programming securityEuropean patriotism,入手,break out

4、of the strict LIFO regime of block instances,措施,A procedure-like activity declarationExplicit process pointers for dynamic naming and referencingA mechanism for accessingmechanisms for the scheduling and sequencing of processes,实现,writing a new runtime system(garbage collector)compiler extensions:bl

5、ock prex“SIMULA”,兼容Algol60,Simula I,思考,activity/process:useful for programming and system design in generalobjects belonging to different classes having common properties,Classresume operator is a basic coroutine call defined for whole languageinheriting,方法,more,bottom up program designtop down orie

6、nted mechanism through a concept of virtual procedures“garbage collectorforbidding class prefixing across block levelsTony Hoare:abstraction function“OO paradigm,Simula 67,SmalltalkBETAC+EiffelJAVA,Bjarne Stroustrup,Denmark Ph.D,University of CambridgeAT&T Labs,College of Engineering Chair Professor

7、 in Computer Science at Texas A&M UniversityMember of the National Academy of Engineering in 2004ACM、IEEE Fellowhttp:/,designed and implemented C+,课程内容,C+程序设计基础 C+程序设计 钱能 清华大学出版社C+程序设计技巧 Effective C+More Effective C+Thinking in C+,侯捷,考核方式,机考50%平时测验40%210%+20%作业 10%笔试50%,参考书,PrincipleThe Annotated C+

8、Reference Manual,Margaret A.Eillis and Bjarne Stroustrup,Addison-Wesley,1990,ISBN 0-201-51459-1The Design and Evolution of C+,Bjarne Stroustrup,Addison-Wesley,1994,ISBN 0-201-54330-3C+Primer,Fourth Edition,Stanley B.Lippman,Josee LajoieProgramming-Principles and Practice Using C+Bjarne Stroustrup,Ad

9、dison-Wesley ISBN 978-0321543721,December 2008,参考书,Language&Standard LibraryThe C+Programming Language(Third Edition),Bjarne Stroustrup,Addison-Wesley,1998,ISBN 0-201-92488-9special edition 2000Thinking in C+,Bruce Eckel,Prentice Hall,1995,参考书,ProgrammingEffective C+,Second Edition:50 Specific Ways

10、to Improve Your Programs and Designs,Scott Meyers,Addison-Wesley,1998,ISBN 0-201-92488-9More Effective C+:35 New Ways to Improve Your Programs and Designs,Scott Meyers,Addison-Wesley,ISBN 0-201-63371-XC+Strategies and Tactics,Robert Murray,Addison-Wesley,1993,ISBN 0-201-56382-7,Generic Programming E

11、fficient,Reusable,参考书,SamplesC+Programming Style,Tom Cargill,Addison-Wesley,1992,ISBN 0-201-56365-7OthersAdvanced C+:Programming Styles and Idioms,James Coplien,Addison-Wesley,1992,ISBN 0-201-54855-0Designing and Coding Reusable C+,Martin D.Carroll and Margaret A.Ellis,Addison-Wesley,1995,ISBN 0-201

12、-51284-X,参考书,OthersScientific and Engineering C+,John J.Barton and Lee R.Nackman,Addison-Wesley,1994,ISBN 0-201-53393-6Design Patterns:Elements of Reusable Object-Oriented Software,Erich Gamma,Richard Helm,Ralph Johnson,and John Vlissides,Addison-Wesley,1995,ISBN 0-201-63361-2,C和C+,C BCPL(Martin Ric

13、hards)B(Ken Thompson)C(Dennis Ritchie)Unix的开发语言 1972ANSI C 1989 Kernighan Ritchie 可应用于多种技术领域和多种平台的开发系统-从最小的嵌入式处理器到最大的超级计算机和数据处理系统主要特点语言简洁、紧凑可直接访问内存,胜任OS的开发目标代码质量高、运行效率高具有良好的可移植性,C和C+,C+“C with class”Bjarne Stroustrup1980 年 贝尔实验室1983年取名为C+Rick Mascitti ANSI C+标准草案1994年主要特点完全包含C语言成分(C的超集)添加了OOP的完全支持,C

14、+支持 C 所支持的全部编程技巧,任何 C 程序都能被 C+用基本相同的方法编写,并具备相同的时间和空间开销,Programmer needs to be trusted,与可能出现的错误相比,更重要的是能做什么好的事情,Programming Paradigm,Procedural Paradigmbased upon the concept of the procedure callObject-Oriented ParadigmThe theory of concepts,and models of human interaction with real world phenomena,

15、Imperative programming,Programming Paradigm,Functional ParadigmMathematics and the theory of functionsLisp(atom,list,cons,)app:EmacsLogicalAutomatic proofs within artificial intelligenceBased on axioms,inference rules,and queriesprolog,declarative programming,Haskell,程序设计范型,结构化程序设计功能分解、逐步求精单入口、单出口的三

16、种控制结构缺点数据和操作的分离使得程序难以理解重用性差,程序设计范型,面向对象程序设计本质对象将数据和处理数据的过程当成一个整体封装 vs 信息隐藏继承 vs 重用多态性动态定连(Dynamic Binding)一名多用、类属,程序定律,结构化程序设计程序数据结构算法面向对象程序设计程序对象对象对象“消息”,结构化程序设计部分,语言的组成,三要素Syntax、Semantics、PragmaticsData StructureAlgorithm数据名、类型、值、地址、性质数据处理操作算术(移位)、逻辑、IO控制流顺序、选择、重复,ADT抽象数据类型,BackusNaur FormCFG,nat

17、=0-9+signedNat=(+|-)?natNumber=signedNat(.nat)?(E signedNat)?,letter=a-zA-Zdigit=0-9identifier=letter(letter|digit)*,语用乃语言成分在程序特定执行中的实际效用相对性、动态性、多元性,You have a green light,“Pragmatics studies the factors that govern our choice of languagein social interaction and the effects of our choice on others.

18、”,类型,类型系统静态/动态弱/强C+是强类型语言要求程序设计者在使用之前对数据的类型进行声明隐式转换 coersion显式转换 casting,基本数据类型(primitive),char、int、float、doubleModifiers:long、short、signed、unsignedchar 只能用signed、unsigned修饰float 不能被修饰double 只能用long修饰int 可以用4种修饰符组合修饰省略表示操作符 sizeofANSI C+:wchar_t、bool,基本数据类型,typedef为已有的类型定义一个同义词typedef double profit;

19、typedef int INT;,表达式,操作数、操作符和标点符号组成的序列,表示一个计算过程优先级a+b*c结合性a+b-c求值次序(a+b)*(a-b)与编译系统有关类型转换约定 int x=10;float y=2.0;x*y,表达式,计算与类型相同类型的两个操作数运算后,其结果仍然为该类型的值类型对计算的限制类型具有取值范围,超出取值范围的值没有意义混合类型计算和类型转换转换总是朝表达能力更强的方向,并且转换总是逐个运算符进行自动转换(coersion)显式转换(casting),表达式,求值次序与副作用操作数的求值次序在ANSI C+中没有规定,由各编译系统自行决定。不同的编译系统求

20、值顺序不同int a=3,b=5;c=a*b+b;求值次序使交换率失去作用int a=3;c=a+*+a;副作用的危害破坏了可移植性降低了程序的可读性消除副作用,表达式,表达式种类算术表达式关系和逻辑表达式赋值表达式逗号表达式字位运算符表达式操作符可重载,表达式,赋值表达式左值右值表达式左值:可以出现在赋值表达式左部的表达式,具有存放数据的空间类型不同时,先计算右值表达式的值,再转换为左值类型,然后赋值算术表达式增量和减量操作符前增量(前减量)+a(-a)前增量的结果是左值后增量(后减量)a+(a-)提高编译结果的执行效率,表达式,条件运算符表达式?:唯一的三目运算符只计算一个运算分量如果 和

21、的值类型相同,且均为左值,则该条件运算符表达式为左值表达式可嵌套sign(x)x 0?1:x=0?0:-1就近原则,表达式,逗号表达式,的值作为该逗号表达式的值int a,b,c;d=(a=1,b=a+2,c=b+3);cout 为左值,则该逗号表达式为左值,表达式,字位运算符表达式对整型数二进制位(bit)的操作,将整型数看作二进制序列取反、与&、或|、异或 按位取反 单目按位与&双目复位按位或|双目置位异或 双目与全0的二进制串的运算不变与全1的二进制串的运算取反与本身的运算清零与同一个对象运算两次还原移位运算符表达式,语句,表达式语句IO语句cin、cout iostream.h、可重载

22、控制流语句顺序、选择、重复,iostream,stdio.h,语句,switchswitch 后必须是整型表达式,case 后必须是整型常量表达式值各不相同各个case(包括default)出现的次序可以任意case 仅起标号作用,不改变执行顺序break多个case可以公用一组语句通常可以和if语句配合使用,enum,IO,函数,原则函数定义不允许嵌套先定义后使用函数的执行机制建立被调用函数的栈空间保存调用函数的运行状态参数传递值传递(call by value)引用传递(call by reference)保存返回地址将控制转交被调函数,Call by name Call by value

23、-result,Runtime Environment,void p(int x)+i;+x;int a10;int i=1;a1=1;a2=2;p(ai);,void p(int x,int y)+x;+y;int a=1;p(a,a);,Call by name:delayed evaluation,Call by value-resultcopy-restore,_stdcall _cdecl_fastcall,函数,函数原型遵循先定义后使用原则自由安排函数定义的位置标准库函数的函数原型都在头文件(.h)中提供,用#include 指令包含这些原型文件用户自定义的函数必须在源代码中说明函

24、数原型函数原型是一条语句函数原型不必含有参数的名字,只需含有参数的类型函数原型必须和函数定义在返回值类型、函数名和参数表完全一致,编译器在遇到函数调用时,需检查函数原型,函数,函数重载原则一组重载函数,相互间至少在参数个数、类型或顺序上有所不同返回值类型不作为区别重载函数的依据匹配重载函数的顺序严格内部转换用户定义的转换void f(long);void f(double);f(10);ambiguous,Name manglingextern“C”,函数,带默认参数的函数默认参数的声明函数原型中给出先定义的函数中给出默认参数的顺序规定从右到左,中间不能间断默认参数与函数重载void f(in

25、t);void f(int,int=2);ambiguous,函数,内联函数inline目的提高程序的可读性提高程序的运行效率对象使用频率高的小段代码实现方法编译系统将为 inline 函数创建一段代码,在每次调用时,用相应的代码替换限制非递归由编译系统控制,函数,明智地运用inlining(Use inlining judiciously)只是对编译系统的提示Big/complex(loop,switch)/Function pointerCompiler(outlined)static functionrecompile/link vs rebuild缺点增大目标代码(object cod

26、e)病态的换页(thrashing)降低指令快取装置的命中率(instruction cache hit rate),程序结构,程序结构逻辑结构物理结构多个源文件组成 只能其中一个文件含有主函数工程文件外部函数外部变量extern,main,f1,f2,fn,cpp1,cpp2,cpp3,obj1,obj2,objn,Compiler,exe,Lib,Linker,const double pi=3.14;,int count=0;,void show().,void process()int i=0;while()char c;,a.cpp,float salary;,static,stat

27、ic,extern void show();,extern float salary;,a.h,int count=0;,void process()salary=100;for()char c;show();,b.cpp,static,static,#include“a.h”,int k=0;,static,程序级,文件级,函数级,块级,Code,Data,Stack,Heap,namespace,const.h,const double pi=3.14;,#include“const.h”,#include“const.h”,void main()int x;.;,编译预处理,常量定义,变

28、量/函数声明,内联函数,类型定义,作用域与生命期,程序的局部性原则程序的内存结构Code、Global data、Stack、HeapScope全局变量static局部变量静态局部变量static(生命期),程序结构,Static global variable static 防止名冲突值可靠Static function限制使用对函数定义的补充static Constant缺省为 static开放 extern,程序结构,标识符在程序中有效的范围程序级外部量、外部函数文件级静态函数、静态全局量函数级标号、形式参数、局部量块级可见性分析在某一位置标识符的有效性:引用全局变量namespaceu

29、sing namespce,int global;/程序级void f()/程序级static float f;/文件级static void g()/文件级 void main()int x;/函数级 if(x0)float x=0;/块级,多文件结构,Header File声明的部分宏定义包含指令类型定义函数声明内联函数常量定义变量声明,编译预处理,包含#include“”宏定义define 字符串字符串undef宏名字带参数的宏条件编译#if#else#elif#endif#ifdef#ifndef设定编译器状态#pragmaoncewarning(disable:4101)warnin

30、g(error:160),数组,特征相同数据类型有序连续存储0n-1一维数组类型定义函数参数仅传递地址元素个数需通过参数显示给出,不能通过sizeof 取得字符串,数组,多维数组定义T Ac1c2存储组织参数传递只能缺省第一维降维处理,typedef T A1c2;A1 Ac1;,数组,void f(int a,int n);void f(int a3,int n);char s1=abc;cout s1;char s2=a,b,c;cout s2;char s33;s3=abc;,char s2=a,b,c,0;,X,结构和联合,struct赋值同类型alignment参数传递union共享

31、存储空间,_declspec(align(8)#pragma pack(n),结构和联合,enum FIGURE_TYPE LINE,RECTANGLE,ELLIPSE;struct Line struct Rectangle FIGURE_TYPE t;FIGURE_TYPE t;int x1,x2,y1,y2;int left,top,right,bottom;;struct Ellipse FIGURE_TYPE t;int x,y,r;;union FIGUREFIGURE_TYPE t;Line line;Rectangle rect;Ellipse ellipse;,例:定义一个能

32、存储100个图形的数组,其中的图形可以是:直线、矩形、圆,FIGURE figures100;void main()input(figures,100);for(int i=0;i100;i+)draw(figuresi);void draw_line(int,int,int,int);void draw_rect(int,int,int,int);void draw_ellipse(int,int,int);,结构和联合,void draw(FIGURE figure)switch(figure.t)case LINE:draw_line(figuresi.line.x1,);break;c

33、ase RECTANGLE:draw_rect(figuresi.rect.left,);break;case ELLIPSE:draw_ellipse(figuresi.ellipse.x,);break;,void input(Figure fig,int size)int t;for(int k=0;k t;switch(t)case LINE:figk.type=LINE;cin figk.line.x1 figi.line.y1 figk.line.x2 figi.line.y2;break;case RECTANGLE:case ELLIPSE:.,多态性,指针,管理地址信息 按地

34、址管理数据指针定义与基本操作指针与函数指针与数组指针与结构多级指针动态变量,指针定义与基本操作,定义格式*int*p;/p为一个指针变量定义多个指针变量时,每个指针变量前都要有*int*p,*q;/p和q均为指针变量int*p,q;/p为指针变量,q为整型变量用 typedef 定义一个指针类型 typedef int*Pointer;Pointer p,q;/p和q均为指针变量赋值 int*p=0 x12345678;int*p=(int*)0 x12345678;,指针定义与基本操作,操作符,9,x,0X5A12,p,0X7B77,0X5A12,1000,指针定义与基本操作,指针指向一个变

35、量:指针变量的值为另一个变量的地址Pointer literal 0、NULL 不指向任何对象初始化!,p,1000,x,指针定义与基本操作,指针运算赋值同类型赋值 int x;double d;int*p,*q;p=,指针定义与基本操作,+/-整型值一个指针值可以与一个整型值进行+/-运算,结果为同类型的指针值int x;int*p;p=p+1;p=/q的值加8(sizeof(double),指针定义与基本操作,同类型指针相减同类型的指针值可以相减,结果为整型值int*p,*q;int offset;offset=p-q;int a10;int*p,*q,offset;p=/offset=3

36、,指针定义与基本操作,同类型指针比较=、!=一般不使用、=、=输出int x=1;int*p=/p指向的字符,即:Acout(void*)p/p的值,指针定义与基本操作,void*只管理地址信息 void*p;任何类型的指针均可以赋值给void*void*any_pointer;int x;double y;any_pointer=不能进行其他指针运算和间接引用,除非做强制类型转换*any_pointer/error*(int*)any_pointer)/OK*(double*)any_pointer)/OK,指针定义与基本操作,例:将某指针所指向的一块内存清零。void memset(voi

37、d*pointer,unsigned size)char*p=(char*)pointer;for(int k=0;ksize;k+)*p+=0;void memset(void*,int,unsigned);EX:void memcpy(void*des,void*src,unsigned size);,指针定义与基本操作,常量指针与指针常量常量指针const*const int x=0;int y;const int*p;/p为指向常量的指针(常量指针)int*q;p=/OK!Why?,constant,P,variable,x(常量),const_cast,消除函数副作用,指针定义与基本

38、操作,指针常量*const 必须在定义时初始化 int x,y;int*const p=/Ok,variable,P(常量),constant,x,const int*const p;?,指针与函数,指针作为行参提高传输效率函数副作用常量指针Function Pointer指向函数的指针,double f(int x)int g()void main()double(*fp)(int);/typedef double(*FP)(int);/FP fp;fp=f;fp=/Error,函数指针,函数参数 编写函数,使其能计算任意一元函数在某区间上的定积分#include double integr

39、ate(double(*f)(double),double a,double b)f(x),a,b,double my_func(double x)void main()integrate(sin,0,1);integrate(cos,1,2);integrate(my_func,1,10);,示例,sort,int scompare(const void*elem1,const void*elem2)TStudent*p1=(TStudent*)elem1;TStudent*p2=(TStudent*)elem2;return strcmp(p1-name,p2-name);,void My

40、Sort(void*base,unsigned num,unsigned width,int(*compare)(const void*elem1,const void*elem2)char*A=(char*)base;char*tmp=(char*)malloc(width);for(unsigned i=1;i0)/Aj Aj+1)memcpy(tmp,A+j*width,width);/int tmp=Aj;memcpy(A+j*width,A+(j+1)*width,width);/Aj=Aj+1;memcpy(A+(j+1)*width,tmp,width);/Aj+1=tmp;fr

41、ee(tmp);,TStudent student=;int num=sizeof(student)/sizeof(student0);int width=sizeof(student0);MySort(student,num,width,icompare);,CALLBACK,指针与数组,数组元素操作下标表达式访问效率数组元素的指针表示法一维数组多维数组,int b2010;/typedef int A10;A b20;int*q;q=bij*(*(b+i)+j)*(*(p+i)+j)pij,int a10;int*p;int i;p=ai*(a+i)*(p+i)pi&ai a+i p+i&

42、pi,指针与数组,#include int maximum(int grade,int num)int max=0;for(int k=0;k max)max=gradek;return max;void main()int A24=68,69,70,71,85,86,87,89;cout“the max grade is”maximum();,sizeof(A)/sizeof(A00),maximum(,A0,2*4,指针与数组,指针数组 数组中的元素为指针char*s1=“C+”,“PASCAL”,“FORTRAN”;char s28=“C+”,“PASCAL”,“FORTRAN”;,s1

43、,C+0,P A S C A L 0,F O R T R A N 0,s2,指针数组,main 函数int main(int argc,char*argv,char*env)argc:参数个数argv:命令行参数env:环境参数argc:3env:,cmd:set,system(“test.exe”),C/C+标准int main()int main(int argc,char*argv),#include#include using namespace std;void MyPrint(char*s,.)va_list marker;va_start(marker,s);int i=0;ch

44、ar c;while(c=si)!=0)if(c!=%)cout c;else i+;switch(c=si)case f:cout va_arg(marker,double);break;case d:cout va_arg(marker,int);break;case c:cout va_arg(marker,char);break;i+;cout endl;va_end(marker);,/platform:x86typedef char*va_list;#define _INTSIZEOF(x)(sizeof(x)+sizeof(int)-1)&(sizeof(int)-1)#defi

45、ne va_start(ap,v)(ap=(va_list)&v+_INTSIZEOF(v)#define va_arg(ap,t)(*(t*)(ap+=_INTSIZEOF(t)-_INTSIZEOF(t)#define va_end(ap)(ap=(va_list)0),格式化串攻击,(x+n-1)/nn(x+n-1)/n)*n(x+n-1)&(n-1),Ex:int max(int num,),void main()MyPrint(double:%f integer:%d string:%c,1.1,100,A);,指针和结构,结构成分的访问(*p).x p-x结构作为函数参数大块数据传

46、输const,多级指针,指针变量所指向的数据类型为指针类型int*pp;/pp为指针变量,指向另一个指针变量(int*)int*p;int x=2;p=指针变量必须初始化或赋值,否则将会导致运行时刻的严重错误,多级指针,编写一个函数,交换两个字符串void swap(char*p1,char*p2)char*tmp=*p1;*p1=*p2;*p2=tmp;void main()char*p1=abcd;char*p2=1234;cout p1 p2 endl;swap(,动态变量,动态变量编译时刻无法确定在程序运行时刻,动态产生、消亡通过指向动态变量的指针变量来实现的分配在堆区(heap)局部

47、变量也是动态产生、消亡,但在程序运行前,编译程序已经知道它们的存在动态变量与C+中的静态(static)变量属于不同的范畴,动态变量是程序设计的概念,static 是C+语言的概念,动态变量,动态变量的产生 操作符new new,int*p=new int10;int(*p2)5=(int(*)5)p;for(int i=0;i10;i+)pi=i+1;for(int j=0;j2;j+)for(int k=0;k5;k+)cout p2jk;cout endl;,typedef int i5Array 5;void main()i5Array*p=new i5Array 2;for(int

48、j=0;j2;j+)for(int k=0;k5;k+)pjk=(j*5)+(k+1);,动态变量,动态变量的产生 函数mallocvoid*malloc(unsigned int size)p=(int*)malloc(sizeof(int);/new int q=(int*)malloc(sizeof(int)*20);/new int 20new vs mallocnew自动返回相应类型的指针,malloc 要作强制类型转换。如果创建的是动态对象,new会去调用相应类的构造函数,malloc 则否异常控制必须在判断申请的空间有效的情况下,才能使用,动态变量,动态变量的消亡动态变量不会自动

49、消亡,在程序运行期间,如果不再需要某个动态变量,应显式地使之消亡,否则将造成memory leak操作符:new delete函数:malloc freedelete,cookie,动态变量的应用,数据结构链表(单、双)栈、队列树、图结点的定义 struct NODE int content;NODE*next;NODE*head=NULL;,单链表,结点的插入产生一个新结点:NODE*p=new NODE;p-content=some_int_value;p-next=NULL;链表为空 head=p;表头插入 p-next=head;head=p;,单链表,表尾插入 NODE*q=head

50、;while(q-next)q=q-next;q-next=p;插在链表中某结点(值为a)的后面 NODE*q=head;while(q,单链表,插在链表中某结点(值为a)的前面 NODE*q1=NULL,*q2=head;while(q2,guard node,单链表,结点删除(假设结点值为a)NODE*q1=NULL,*q2=head;while(q2,单向排序链,struct Nodevoid print()int k;Node*p=first;Node*next;while(p)*first=NULL;cout k next;void release()while(first!=NUL

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号