版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C++编程练习题(带答案)一、单项选择题(共10题,每题侧重考察C++核心语法、标准规范与常见易错点,每题只有一个正确选项)1.下列关于const修饰符的指针声明中,允许通过指针修改所指向内存空间存储值的是()A.constint*p=&a;B.int*constp=&a;C.constint*constp=&a;D.intconst*p=&a;【答案】B【解析】const修饰指针的规则可以总结为“左定值、右定向”:当const位于*运算符左侧时,修饰的是指针指向的内容,即无法通过该指针修改指向内存的值,但指针本身的指向可以修改;当const位于*运算符右侧时,修饰的是指针本身,即指针的指向无法修改,但可以通过指针修改指向内存存储的值。对各选项分析如下:选项A和选项D的声明完全等价,const均位于*左侧,属于指向常量的指针,无法通过指针修改指向值;选项C中const同时出现在*的左右两侧,指针本身的指向和指向的内容均不可修改;选项B中const位于*右侧,属于常量指针,指针固定指向变量a的地址,可以通过*p修改a的值,符合题干要求。2.下列关于C++中new/delete与malloc/free的描述,正确的是()A.malloc分配内存失败时会抛出std::bad_alloc异常,new分配失败会返回NULLB.new在申请自定义类型内存时会自动调用类的构造函数,delete释放内存时会自动调用类的析构函数C.malloc和new申请的内存可以交叉使用free和delete释放,不会产生运行错误D.new[]申请的数组内存,使用delete而非delete[]释放也能正确回收所有资源,不会造成内存泄漏【答案】B【解析】new/delete是C++的运算符,malloc/free是C标准库函数,二者的核心差异在于对自定义类型的生命周期管理:new在分配内存后会调用对象的构造函数完成初始化,delete在释放内存前会调用对象的析构函数完成资源清理,而malloc/free仅负责原始内存的分配和释放,不会调用构造或析构函数。对各选项分析如下:选项A错误,malloc分配失败时返回NULL空指针,new默认分配失败时抛出std::bad_alloc异常,只有使用std::nothrow参数的new版本才会在失败时返回NULL;选项C错误,malloc申请的内存必须使用free释放,new申请的内存必须使用delete释放,混用会导致行为未定义——例如对new创建的自定义类型对象调用free,会跳过析构函数调用导致资源泄漏,对malloc申请的内存调用delete,会对未初始化的内存执行析构逻辑引发程序崩溃;选项D错误,new[]申请的对象数组必须使用delete[]释放,delete仅会调用数组第一个元素的析构函数,剩余元素的析构函数不会执行,必然造成资源泄漏甚至程序崩溃。3.下列关于C++引用的描述,错误的是()A.引用在声明时必须完成初始化,且初始化绑定到某个对象后,不能再重新绑定到其他对象B.引用作为函数参数传递时,具有传址语义,不会产生实参的临时副本,适合传递大尺寸对象C.C++98标准下可以定义指向引用的指针,也可以定义引用的引用D.函数返回值为引用类型时,不能返回局部栈变量的引用,否则会产生悬空引用引发未定义行为【答案】C【解析】引用是C++对变量的别名机制,语法层面引用不是独立的对象,不占用独立的内存空间(编译器实现层面通常通过指针模拟引用的语义,但语法上不将其视为独立对象)。对各选项分析如下:选项C错误,C++98标准下不存在“指向引用的指针”或“引用的引用”,因为引用本身不是对象,没有独立的内存地址,无法被指针指向,也无法作为引用的绑定目标,C++11引入的右值引用和引用折叠规则是新标准的扩展,不属于C++98的标准范畴;选项A正确,引用必须在声明时初始化,绑定关系一旦确立无法修改;选项B正确,引用传参避免了值传递的拷贝开销,同时可以通过const引用实现常量传递;选项D正确,局部栈变量在函数返回后会随着栈帧销毁而失效,返回其引用会导致访问已回收的内存空间,属于典型的未定义行为。4.下列关于C++虚函数与多态的描述,正确的是()A.类的构造函数可以声明为虚函数,析构函数不能声明为虚函数B.类中声明了纯虚函数时,该类为抽象类,无法实例化对象;其派生类如果没有实现所有纯虚函数,仍然是抽象类C.虚函数的调用在编译阶段即可确定具体调用的函数版本,属于静态绑定D.类的友元函数可以声明为虚函数,因为友元函数拥有类成员的访问权限【答案】B【解析】多态是面向对象的核心特性,通过虚函数实现运行时动态绑定。对各选项分析如下:选项B正确,纯虚函数是只声明接口、未提供实现的虚函数,包含纯虚函数的类是抽象类,不能创建对象;派生类必须实现所有继承的纯虚函数才能成为可实例化的具体类,未完全实现纯虚函数的派生类仍然是抽象类。选项A错误,构造函数不能声明为虚函数——虚函数的调用依赖对象内存中的虚函数表指针,而虚表指针是在构造函数执行过程中才完成初始化的,构造时对象的动态类型尚未完整,无法支持虚函数的动态绑定;作为多态基类使用的类,析构函数必须声明为虚函数,否则通过基类指针释放派生类对象时会因未调用派生类析构函数引发资源泄漏。选项C错误,非虚函数的调用在编译期根据指针/引用的静态类型绑定,属于静态绑定;虚函数的调用在运行时根据对象的实际动态类型绑定,属于动态绑定。选项D错误,虚函数必须是类的非静态成员函数,友元函数不属于类的成员,无法声明为虚函数。5.下列STL容器中,支持在已获取迭代器的位置实现O(1)时间复杂度的插入和删除操作,且不支持下标随机访问的是()A.std::vectorB.std::listC.std::dequeD.std::array【答案】B【解析】不同STL容器的底层数据结构不同,决定了其操作的时间复杂度差异:std::list底层为双向循环链表实现,每个节点独立存储,节点通过指针连接,在已知迭代器的位置插入或删除节点仅需要修改相邻节点的指针,时间复杂度为O(1);由于链表内存不连续,无法通过下标偏移直接访问元素,只能通过迭代器双向遍历,不支持随机访问,因此选项B正确。其余选项分析如下:std::vector和std::array底层为连续内存数组,支持O(1)时间的下标随机访问,但在中间位置插入或删除元素需要移动后续所有元素,时间复杂度为O(n);std::deque为分段连续的双端队列,支持O(1)时间的下标随机访问(效率略低于vector),头尾插入删除为O(1),中间位置插入删除为O(n)时间复杂度。6.下列关于C++运算符重载的描述,错误的是()A.运算符重载不能改变运算符的原有优先级、结合性,也不能改变运算符所需要的操作数个数B.赋值运算符=、下标运算符[]、函数调用运算符()、箭头成员访问运算符->只能作为类的成员函数重载,不能作为全局友元函数重载C.重载后置自增运算符++时,参数列表需要添加一个int类型的哑元参数,用于和前置自增运算符做区分D.可以通过运算符重载创建C++标准中不存在的新运算符,例如定义运算符实现幂运算功能【答案】D【解析】运算符重载是对已有运算符赋予自定义类型的操作逻辑,但不能改变运算符的基本语法规则。选项D错误,C++规定运算符重载只能针对语言标准已定义的运算符,不允许创造新的运算符,因此无法定义作为新的幂运算符。其余选项描述均符合规范:选项A明确了运算符重载的边界,重载后的运算符仍然保持原有的语法属性;选项B列出的四个运算符由于语言规则限制,必须作为类成员函数重载,若定义为全局函数会与编译器默认生成的成员函数产生歧义;选项C区分了前后置自增运算符的重载形式,前置++的签名为T&operator++(),后置++的签名为Toperator++(int),其中int参数无实际传值意义,仅作为标识区分重载版本。7.下列关于C++中static关键字的用法,描述错误的是()A.函数内部声明的static局部变量存储在静态存储区,仅在第一次执行到声明语句时初始化一次,函数调用结束后变量不会被销毁,生命周期持续到程序运行结束B.类内部声明的static静态成员变量属于整个类所有,不占用单个类对象的内存空间,需要在类的作用域外单独进行初始化C.全局作用域下声明的static全局变量具有外部链接属性,可以在其他源文件中通过extern关键字声明后直接访问D.类内部声明的static静态成员函数没有隐式的this指针,不能访问类的非静态成员变量和非静态成员函数,只能操作类的静态成员【答案】C【解析】static关键字在不同场景下具有不同的语义:选项C错误,全局作用域下用static修饰的变量或函数具有内部链接属性,仅能在当前源文件内被访问,其他源文件无法通过extern声明访问;未加static修饰的全局变量和函数才具有外部链接属性,可被其他源文件访问。其余选项描述均正确:静态局部变量存储在全局静态区,仅初始化一次,生命周期贯穿程序全程;静态成员变量不属于具体对象,存储在静态区,必须类外初始化(C++17支持inline静态成员类内初始化);静态成员函数属于类本身,不绑定具体对象,因此没有this指针,只能访问静态成员。8.下列关于C++强制类型转换运算符的使用场景,描述正确的是()A.static_cast可以用于类层次结构中的下行转换(基类指针转派生类指针),且转换时会执行运行时类型检查,转换不安全时返回空指针B.dynamic_cast主要用于具有多态性的类层次结构中的指针或引用转换,下行转换时会执行运行时类型检查,指针转换失败返回nullptr,引用转换失败抛出std::bad_cast异常C.const_cast可以去除任意类型的常量属性,即使是const修饰的全局常量,也可以通过const_cast转换后安全修改,不会产生未定义行为D.reinterpret_cast是最安全的强制类型转换,会在转换时自动做类型对齐检查和值调整,适合任意指针类型和数值类型的互相转换【答案】B【解析】C++提供了四种命名的强制类型转换运算符,替代C风格的强制转换,明确转换意图、降低转换风险。选项B正确描述了dynamic_cast的功能:dynamic_cast仅能用于含虚函数的多态类型的指针/引用转换,运行时会检查对象的实际类型是否匹配转换目标,安全性高。其余选项错误分析如下:选项A错误,static_cast执行编译期的类型检查,下行转换时不会做运行时校验,转换安全性由开发者保证,若基类指针实际不指向派生类对象,转换后使用会引发未定义行为;选项C错误,const_cast仅能去除指针或引用的const属性,若被转换的对象本身是const常量(尤其是存储在只读数据段的全局const常量),修改其值会触发内存访问错误,属于未定义行为;选项D错误,reinterpret_cast是最低级的类型转换,直接重新解释内存中的比特位,不做任何类型检查和对齐调整,转换风险极高,仅在底层开发中必要时使用。9.下列哪组函数构成合法的C++函数重载(不存在编译阶段的重定义错误)()A.intfunc(inta);和voidfunc(inta);B.voidfunc(inta,doubleb);和voidfunc(doubleb,inta);C.intfunc(inta=10);和intfunc();D.intfunc(int*a);和intfunc(int*consta);【答案】B【解析】C++函数重载的规则是:同一作用域内,函数名相同但参数列表存在可区分的差异(参数类型、个数、顺序不同),即可构成重载,返回值类型不参与重载判定。对各选项分析如下:选项A两个函数参数列表完全一致,仅返回值不同,无法构成重载,编译时会报函数重定义错误;选项C中第一个函数的int类型参数带有默认值,函数签名本质为intfunc(),与第二个无参函数的签名完全一致,构成重定义,且无参调用时会出现二义性;选项D中第二个参数的const是顶层const,修饰指针本身(即指针变量为常量),由于函数参数是值传递,顶层const不参与参数类型区分,两个函数的参数类型均为int*,无法构成重载;选项B的两个函数参数顺序存在明确差异,第一个参数分别为int、double类型,第二个参数分别为double、int类型,参数列表可被编译器明确区分,构成合法重载,需要注意的是调用时若传入两个int类型实参,会因隐式转换匹配到两个函数产生调用二义性,但函数声明本身符合重载规则,不存在编译错误。10.下列关于C++11标准中智能指针的描述,错误的是()A.std::unique_ptr是独占式智能指针,不支持拷贝构造和拷贝赋值,只能通过移动语义转移所管理对象的所有权B.std::shared_ptr是共享式智能指针,通过线程安全的引用计数机制管理对象生命周期,当最后一个指向对象的shared_ptr销毁时,自动释放所管理的堆内存C.std::weak_ptr是为解决shared_ptr循环引用问题设计的辅助智能指针,它不持有对象的所有权,不增加引用计数,可以通过lock()方法获取指向对象的有效shared_ptrD.std::auto_ptr是C++11新引入的智能指针,支持移动语义,比unique_ptr安全性更高,在现代C++开发中推荐优先使用【答案】D【解析】std::auto_ptr是C++98标准引入的早期智能指针,其设计存在严重缺陷:拷贝构造和拷贝赋值时会强制转移对象所有权,导致原指针变为悬空状态,且无法适配STL容器的拷贝语义,容易引发内存错误。C++11标准已将auto_ptr标记为废弃,推荐使用语义更明确、安全性更高的unique_ptr替代,因此选项D描述错误。其余选项均符合C++11智能指针的标准规范:unique_ptr采用独占所有权模型,禁止拷贝仅支持移动;shared_ptr通过引用计数实现共享管理,计数归零时自动析构对象;weak_ptr不持有所有权,用于打破循环引用,lock()方法可在对象存活时返回有效的shared_ptr,否则返回空指针。二、程序阅读题(共5题,要求阅读给定代码,写出程序在标准C++规范下的输出结果,重点考察代码逻辑推演、语法细节的实际应用能力)1.给定如下代码,写出程序运行后的标准输出:usingnamespacestd;intmain(){intarr[]={10,20,30,40,50};int*p=(int*)(&arr+1);cout<<*(arr+1)<<","<<*(p-1)<<endl;return0;}【答案】20,50【解析】本题考察数组名与指针的语义差异:数组名arr在大多数表达式中会退化为指向数组首元素的指针,类型为int*,因此arr+1表示向后偏移一个int类型的长度,指向数组的第二个元素20,*(arr+1)的值为20。需要特别注意的是,&arr表示整个数组的地址,类型为指向包含5个int元素的数组的指针(int(*)[5]),因此&arr+1的偏移量是整个数组的长度(5*sizeof(int)),指向数组最后一个元素之后的内存位置;将其强制转换为int*类型后赋值给p,p指向数组尾后位置,p-1表示向前偏移一个int类型的长度,指向数组最后一个元素50,因此*(p-1)的值为50。本题的易错点是将&arr误判为首元素地址,导致p的位置计算错误。2.给定如下代码,写出程序运行后的标准输出:usingnamespacestd;classBase{public:Base(){cout<<"B";}~Base(){cout<<"~B";}};classMember{public:Member(){cout<<"M";}~Member(){cout<<"~M";}};classDerived:publicBase{public:Derived(){cout<<"D";}~Derived(){cout<<"~D";}private:Memberm;};intmain(){Derivedd;cout<<endl;return0;}【答案】BMD~D~M~B【解析】本题考察派生类对象的构造与析构顺序:派生类对象构造时,严格按照“基类构造函数→成员对象构造函数(按成员在类中声明的顺序)→派生类自身构造函数”的顺序执行;析构顺序与构造顺序完全相反,即“派生类自身析构函数→成员对象析构函数→基类析构函数”。创建Derived类对象d时,首先调用基类Base的构造函数输出字符B,随后调用成员对象m的构造函数输出字符M,最后调用Derived自身的构造函数输出字符D,因此第一行输出为BMD。main函数结束时对象d销毁,首先执行Derived自身析构函数输出~D,随后执行成员m的析构函数输出~M,最后执行基类Base的析构函数输出~B,因此第二行输出为~D~M~B。3.给定如下代码,写出程序运行后的标准输出:usingnamespacestd;classA{public:virtualvoidfunc(){cout<<"A::func";}voidbar(){cout<<"A::bar";}};classB:publicA{public:voidfunc()override{cout<<"B::func";}voidbar(){cout<<"B::bar";}};intmain(){A*p=newB();p->func();p->bar();deletep;cout<<endl;return0;}【答案】B::funcA::bar【解析】本题考察虚函数的动态绑定机制:p是基类A类型的指针,实际指向派生类B的对象。func是声明为virtual的虚函数,调用时执行动态绑定,在运行时根据对象的实际类型(B)调用派生类重写的B::func;bar是非虚成员函数,调用时执行静态绑定,在编译阶段根据指针的静态类型(A*)调用基类版本的A::bar。本题易错点是误认为派生类重写的bar函数会被调用,实际上非虚函数不会触发多态,调用版本仅由指针/引用的静态类型决定。需要注意的是,本题代码中基类未声明虚析构函数,deletep时存在未定义行为,但题目未涉及析构函数的输出,不影响结果判断。4.给定如下代码,写出程序运行后的标准输出:usingnamespacestd;template<typenameT>Tadd(Ta,Tb){staticintcount=0;count++;cout<<count<<":";returna+b;}intmain(){cout<<add(1,2)<<",";cout<<add(1.5,2.5)<<",";cout<<add(1,2)<<endl;return0;}【答案】1:3,1:4,2:3【解析】本题考察函数模板的实例化规则与静态局部变量的生命周期。C++函数模板本身不是可执行的函数代码,当编译器根据调用时的实参类型推导出模板参数T的具体类型时,才会生成对应类型的独立函数实例,每个独立实例拥有属于自己的静态局部变量,不同实例之间的静态变量互不干扰。第一次调用add(1,2)时,T被推导为int类型,编译器生成int版本的add函数实例,该实例的静态局部变量count初始化为0,执行count++后变为1,输出“1:”,返回1+2=3;第二次调用add(1.5,2.5)时,T被推导为double类型,编译器生成double版本的add函数实例,其静态变量count是独立存储的,初始化为0,自增后为1,输出“1:”,返回1.5+2.5=4(标准输出下浮点数4无小数部分时直接输出4);第三次调用add(1,2)时,仍然匹配int版本的add函数,其count变量已经经过第一次调用的值为1,自增后变为2,输出“2:”,返回3。因此最终拼接的输出结果为1:3,1:4,2:3。该题的易错点是误认为静态count变量被所有模板实例共享,实际上模板实例化是类型安全的代码生成过程,不同类型的实例是完全独立的函数实体。5.给定如下代码,写出程序运行后的标准输出:usingnamespacestd;intmain(){constchar*s[]={"apple","banana","cherry","date"};constcharp=s;p++;cout<<*p<<","<<p<<endl;return0;}【答案】banana,b【解析】本题考察多级指针与字符串数组的语义:s是constchar*类型的数组,每个元素存储一个字符串常量的首地址,数组中的四个元素分别指向"apple"、"banana"、"cherry"、"date"的首字符地址。p是指向constchar*类型的二级指针,初始时指向数组s的第一个元素(即存储"apple"地址的指针变量的位置)。执行p++后,指针向后偏移一个constchar*类型的长度,指向数组的第二个元素(即存储"banana"地址的指针变量的位置)。对p做一次解引用*p,得到数组第二个元素的值,即"banana"字符串的首地址,cout输出constchar*类型时会从首地址开始连续输出字符直到遇到字符串结束符'\0',因此输出banana;对p做两次解引用p,第一次解引用得到"banana"的首字符地址(constchar*类型),第二次解引用得到该地址存储的第一个字符'b',因此输出字符b。三、编程实操题(共3题,由易到难分别考察基础语法应用、面向对象设计、STL综合开发能力,要求写出符合C++11及以上标准、可编译运行、鲁棒性强的代码)1.题目描述:编写程序,输入一个正整数n(1≤n≤10000),输出1到n范围内所有的完数,并统计完数的总个数。完数的定义为:一个正整数恰好等于它的所有真因子(即除自身外能够整除该数的正约数)之和,例如6的真因子为1、2、3,和为6,因此6是完数。要求:实现因子计算时优化时间复杂度,对每个数仅遍历到sqrt(i)即可查找所有因子,避免O(n²)的高复杂度;增加输入合法性校验,若输入的n不在[1,10000]范围内,输出"Invalidinput"并退出程序。【解题思路】本题首先需要做好输入合法性校验,确保输入的n在规定范围内,避免非法输入导致程序逻辑错误。完数判断的核心是真因子求和,若对每个数从1遍历到num-1查找因子,当n为10000时时间复杂度为O(n²),效率较低。优化思路为:对于任意正整数num,如果i是num的因子,那么num/i也必然是num的因子,因此只需要遍历从2到sqrt(num)的范围即可覆盖所有可能的因子,将单个数的因子查找复杂度从O(num)降低到O(sqrt(num)),整体时间复杂度优化为O(n*sqrt(n)),n=10000时仅需要约1e6次运算,效率极高。需要注意边界情况:1的真因子为空集,因此1不是完数,遍历范围从2开始即可;当i和num/i相等时(例如num=4,i=2),只需要累加一次因子值,避免重复计算。【参考代码】usingnamespacestd;intmain(){intn;cin>>n;//输入合法性校验return0;}intperfectCount=0;//1不是完数,从2开始遍历for(intnum=2;num<=n;++num){intfactorSum=1;//1是所有大于1的正整数的真因子intsqrtNum=static_cast<int>(sqrt(num));for(inti=2;i<=sqrtNum;++i){if(num%i==0){factorSum+=i;intotherFactor=num/i;//避免平方数的因子重复累加if(otherFactor!=i){factorSum+=otherFactor;}}}if(factorSum==num){cout<<num<<"";perfectCount++;}}cout<<endl<<"Totalperfectnumbers:"<<perfectCount<<endl;return0;}2.题目描述:设计一个简易的图形类层次结构,要求如下:①定义抽象基类Shape,包含纯虚函数doublegetArea()const(计算面积)、纯虚函数doublegetPerimeter()const(计算周长)、虚函数voidprintInfo()const(输出图形信息,默认输出"Shape");②从Shape派生三个具体类:Circle(圆形)、Rectangle(矩形)、Triangle(三角形);③Circle类包含私有成员radius(半径,double类型),实现面积(πr²)、周长(2πr)计算逻辑,printInfo输出格式为"Circle:radius=x,area=y,perimeter=z";④Rectangle类包含私有成员width、height(宽和高,double类型),实现面积(width*height)、周长(2*(width+height))计算逻辑,printInfo输出格式为"Rectangle:width=x,height=y,area=z,perimeter=w";⑤Triangle类包含私有成员a、b、c(三边长,double类型),构造函数需要验证三边是否满足三角形不等式(任意两边之和大于第三边),若不合法抛出std::invalid_argument异常,面积计算采用海伦公式(半周长p=(a+b+c)/2,面积=√(p(p-a)(p-b)(p-c))),printInfo输出格式为"Triangle:a=x,b=y,c=z,area=m,perimeter=n";⑥编写通用函数voidprintShapeInfo(constShape&s),通过基类常量引用调用printInfo实现多态输出;⑦在main函数中分别创建半径为5的圆形、宽4高6的矩形、三边长3/4/5的三角形,通过通用函数输出所有图形信息,同时测试传入三边长为1/2/3的非法三角形,通过异常捕获输出错误信息。【解题思路】本题考察面向对象编程的核心特性:抽象、继承、多态,以及异常处理的规范使用。首先设计抽象基类Shape,通过纯虚函数定义所有图形必须实现的接口,确保类层次结构的接口一致性;基类必须声明虚析构函数,避免通过基类指针释放派生类对象时出现资源泄漏。派生类分别实现各自的面积、周长计算逻辑,构造函数中对参数合法性进行校验,对非法参数抛出标准异常,符合C++异常处理规范。通用打印函数接受基类引用,通过虚函数的动态绑定实现多态调用,符合开闭原则。三角形类实现时需要注意浮点数精度问题,比较三边关系时引入极小值epsilon消除浮点数计算误差的影响,π值通过acos(-1.0)计算,避免依赖编译器扩展宏,保证代码可移植性。【参考代码】usingnamespacestd;classShape{public:virtualdoublegetArea()const=0;virtualdoublegetPerimeter()const=0;virtualvoidprintInfo()const{cout<<"Shape"<<endl;}//基类虚析构函数,保证派生类对象资源正确释放virtual~Shape()=default;};classCircle:publicShape{private:doubleradius;constexprstaticdoublePI=acos(-1.0);//编译期计算PI值,保证可移植性public:Circle(doubler):radius(r){if(r<=0){throwinvalid_argument("Radiusmustbepositive");}}doublegetArea()constoverride{returnPI*radius*radius;}doublegetPerimeter()constoverride{return2*PI*radius;}voidprintInfo()constoverride{cout<<"Circle:radius="<<radius<<",area="<<getArea()<<",perimeter="<<getPerimeter()<<endl;}};classRectangle:publicShape{private:doublewidth;doubleheight;public:Rectangle(doublew,doubleh):width(w),height(h){}}doublegetArea()constoverride{returnwidth*height;}doublegetPerimeter()constoverride{return2*(width+height);}voidprintInfo()constoverride{cout<<"Rectangle:width="<<width<<",height="<<height<<",area="<<getArea()<<",perimeter="<<getPerimeter()<<endl;}};classTriangle:publicShape{private:doublea,b,c;public:Triangle(doublesideA,doublesideB,doublesideC):a(sideA),b(sideB),c(sideC){constexprdoubleeps=1e-9;//浮点数精度阈值}}doublegetArea()constoverride{doublep=(a+b+c)/2;returnsqrt(p*(p-a)*(p-b)*(p-c));}doublegetPerimeter()constoverride{returna+b+c;}voidprintInfo()constoverride{cout<<"Triangle:a="<<a<<",b="<<b<<",c="<<c<<",area="<<getArea()<<",perimeter="<<getPerimeter()<<endl;}};voidprintShapeInfo(constShape&s){s.printInfo();}intmain(){try{Circlec(5);Rectangler(4,6);Trianglet(3,4,5);printShapeInfo(c);printShapeInfo(r);printShapeInfo(t);//测试非法三角形构造TriangleinvalidT(1,2,3);}catch(constinvalid_argument&e){cout<<"Errorcreatingshape:"<<e.what()<<endl;}return0;}3.题目描述:给定ASCII编码的文本文件input.txt,文件中每行存储一个小写英文单词,单词无重复,长度为1~20,单词总数不超过10000个。编写程序完成以下功能:①读取文件中的所有单词存储到合适的STL容器中,若文件打开失败输出"Failedtoopenfile"并退出;②统计所有单词中a-z每个字母的出现总频次,按照频次从高到低输出字母和对应频次,频次相同的按字母字典序从小到大排序;③实现前缀查找功能:从标准输入读取一个前缀字符串,输出所有以该前缀开头的单词,按字典序从小到大输出,若无匹配单词输出"Nomatchingwords";④要求前缀查找效率尽可能高,避免全量遍历所有单词。【解题思路】本题是文件IO、STL容器、算法、字符串处理的综合应用题,核心是容器选型和效率优化。由于需要支持字典序输出和快速前缀查找,选择std::set<std::string>存储单词为最优方案:set底层为红黑树,元
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 办公室植物课件
- 2026年医院院科两级诊疗质量监督管理制度(3篇)
- 2026年深静脉血栓栓塞症(VTE)培训模拟试题(含答案)
- 2026年华医网考试试题及答案
- 2026年公共卫生执业医师考试《环境卫生学》真题及答案解析
- 2026年广东职业医师考试题库(含答案)
- 2026年道路交通事故处理应急预案
- 2025年处方审核培训考核试题及答案
- 包公审驴课件
- 表格制作指南课件
- 小学道德与法治新部编版六年级上册全册知识点(2026秋)
- 2026年秋招:中国建材笔试题及答案
- 自考09462 国际贸易实务(英语)(短句背诵版适配答题)
- 2026矿区微电网白皮书 多源协控 构建绿色矿区韧性微网-阳光电源
- 新苏教版三年级数学上册第七单元《1.数量关系的分析(1)》课件
- 2026年秋大象版(新教材)小学科学五年级上册教学计划及进度表
- 空压机日常巡检记录
- 地铁通风空调竣工验收监理评估报告
- 2026智联招聘笔试题库及答案
- EDA技术及应用项目教程 教学大纲
- 透析设备维护与管理
评论
0/150
提交评论