【C++】初入嵌入式C++复习-----经典面试题100道


精选 100 道 C++ 笔试题(整理版)

目录

  • 板块一:C++ 与 C 的差异(1--18)
  • 板块二:数据类型、关键字(19--37)
  • 板块三:C++ 面向对象的特性(38--61)
  • 板块四:程序阅读题(62--90)
  • 板块五:编程练习(91--100)

板块一:C++ 与 C 的差异(1--18)

第 1 题:C 和 C++ 中 struct 有什么区别?

参考答案

C C++
Protection 行为 有,默认 private
能否定义函数 否,但可以有函数指针 可以

第 2 题:C++ 中的 struct 和 class 有什么区别?

参考答案:从语法上讲,class 和 struct 做类型定义时只有两点区别:

  1. 默认继承权限:class 的继承默认按 private 处理,struct 的继承默认按 public 处理;
  2. 成员默认访问权限:class 的成员默认 private,struct 的成员默认 public。

除此之外两者基本就是一个东西。


第 3 题:如何判断一段程序是由 C 还是 C++ 编译程序编译的?

标准答案

复制代码
#ifdef __cplusplus
cout << "c++";
#else
cout << "c";
#endif

第 4 题:C 和 C++ 有什么不同?

参考答案:C 是面向过程的(但也可以写面向对象程序);C++ 是面向对象的,提供了类,写面向对象程序比 C 容易。适用方向:C 适合代码体积小、效率高的场合(如嵌入式),Linux 核心大部分是 C 写的;C++ 适合更上层、更复杂的应用。C++ 是 C 的超集,因扩充太多所以叫 c++


第 5 题:"引用"与指针的区别是什么?

参考答案:指针通过指针变量对所指对象间接操作,可读性差;引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。


第 6 题(选择题)

复制代码
class A { virtual void func1(); void func2(); };
class B : class A {
    void func1() { cout << "fun1 in class B" << endl; }
    virtual void func2() { cout << "fun2 in class B" << endl; }
};

A. A 中 func1 和 B 中 func2 都是虚函数

B. 都不是虚函数

C. A 中 func2 是虚函数,B 中 func1 不是

D. A 中 func2 不是虚函数,B 中 func1 是虚函数

标准答案:A


第 7 题:int id[sizeof(unsigned long)]; 这个对吗?为什么?

标准答案:正确。sizeof 是编译时运算符,编译时就确定,可看成和机器有关的常量。


第 8 题:静态全局变量的作用域是( )

A. 只限某个函数 B. 本文件 C. 跨文件 D. 不限制作用域

参考答案:B。静态全局变量只在定义它的源文件内有效,可避免在其它源文件中引起错误。


第 9 题:C++ 函数中值的传递方式有哪几种?

标准答案:三种:值传递、指针传递、引用传递。


第 10 题:频繁使用的短小函数,C 中用什么实现,C++ 中用什么实现?

标准答案:C 用宏定义,C++ 用 inline。


第 11 题:引用与指针有什么区别?

参考答案:

1) 引用必须被初始化,指针不必;

2) 引用初始化后不能改变,指针可以改变所指对象;

3) 不存在指向空值的引用,但存在指向空值的指针。


第 12 题:C++ 中 virtual 与 inline 的含义分别是什么?

参考答案

  • virtual:在基类成员函数声明前加 virtual 即为虚函数。希望派生类重新定义基类方法时,在基类中定义为虚方法,可启用动态联编。
  • inline:inline 与定义体放在一起使函数内联,是用于实现的关键字而非声明的关键字。目的是提高运行效率,代价是代码膨胀;内联函数体不能过长、不能含循环语句。

第 13 题:VC 中 Debug 与 Release 选项的含义?

参考答案:Debug 是调试版本,包含调试信息、不作优化,便于调试,需要相应运行库;Release 是发布版本,进行了各种优化,代码紧凑不含调试信息,可直接运行。


第 14 题:函数 assert 的用法?

参考答案:assert 是仅在 debug 版本起作用的宏,用于检查"不应该"发生的情况,可看作任何系统状态下都可安全使用的无害测试手段。


第 15 题:const 与 #define 的比较,const 有什么优点?

参考答案:

1) const 常量有数据类型,编译器能做类型安全检查;宏常量只是字符替换,没有类型检查,可能产生边际效应错误;

2) 调试工具可以对 const 常量调试,不能对宏常量调试。


第 16 题:请你谈谈引用和指针的区别。

参考答案:

1) 引用被创建时就必须初始化(指针可任何时候初始化);

2) 不能有 NULL 引用,引用必须与合法存储单元关联(指针可以是 NULL);

3) 引用初始化后不能改变关系(指针可随时改变所指对象)。


第 17 题:有了 malloc/free 为什么还要 new/delete?

参考答案:malloc/free 是标准库函数,new/delete 是 C++ 运算符。对象创建时要自动执行构造函数、消亡前要执行析构函数,而 malloc/free 是库函数不在编译器控制范围内,无法强加构造/析构任务。所以需要能完成分配+初始化的 new 和能完成清理+释放的 delete。new/delete 不是库函数。


第 18 题:申请动态内存失败返回 NULL,你是怎么处理内存耗尽的?

参考答案:

1) 判断指针是否为 NULL,是则 return 终止本函数;

2) 是则 exit(1) 终止整个程序;

3) 为 new 和 malloc 设置异常处理函数,如 VC 用 _set_new_handler 为 new 设置自定义异常处理函数。


板块二:数据类型、关键字(19--37)

第 19 题:C++ 是不是类型安全的?

参考答案:不是。两个不同类型的指针之间可以强制转换(用 reinterpret_cast)。


第 20 题:const 符号常量,说明三种描述的区别

复制代码
(1) const char *p
(2) char const *p
(3) char * const p

参考答案:(1) p 是指向 const char 的指针,p 可改变指向,指向的值不能改变;(2) 与 (1) 定义相同;(3) p 是指向 char 的 const 指针,指针本身不可变。


第 21 题:如何判断操作系统是 16 位还是 32 位?

标准答案:定义一个指针 p,打印 sizeof(p),是 4 则 32 位,是 2 则 16 位。


第 22 题:判断 16/32 位,不能用 sizeof()。

参考答案

复制代码
int a = ~0;
if (a > 65536) cout << "32 bit" << endl;
else cout << "16 bit" << endl;

第 23 题:解读复杂指针声明

复制代码
void *(* (*fp1)(int))[10];
float (*(*fp2)(int,int,int))(int);
int (* ( * fp3)())[10]();

标准答案

  1. fp1:指针→函数(参数 int)→ 返回指针→指向数组10→元素为 void* 型指针;
  2. fp2:指针→函数(3 个 int)→ 返回指针→指向函数(参数 int)→ 返回 float;
  3. fp3:指针→函数(参数空)→ 返回指针→指向数组10→元素为指针→指向函数(参数空)→ 返回 int。

第 24 题:虚函数表是 Compile-Time 还是 Run-Time 建立的?

标准答案:虚函数表在编译期建立,各虚函数被组织成入口地址数组;对象的虚函数表指针在运行期(构造函数被调用时)初始化,这是实现多态的关键。


第 25 题:错误的转义字符是( )

A. '\091' B. '\\' C. '\0' D. '\''

标准答案:A


第 26 题:数组名作实参、指针变量作形参,实参传给形参的是( )

A. 数组长度 B. 首元素值 C. 所有元素值 D. 首元素地址

标准答案:D


第 27 题:变量的指针含意是指变量的( )

A. 值 B. 地址 C. 存储 D. 名字

标准答案:B


第 28 题:内存的分配方式有几种?

参考答案:三种。

1) 静态存储区:编译时分配好,运行期间一直存在(如全局变量);

2) 栈上:函数内局部变量在栈上创建,函数结束自动释放,效率高但容量有限;

3) 堆上(动态内存分配):运行时用 malloc/new 申请,程序员负责 free/delete 释放,灵活但问题最多。


第 29 题:float a,b,c,问 (a+b)+c==(b+a)+c(a+b)+c==(a+c)+b 能否成立?

参考答案:两者都不行。float/double 不能简单比较,计算误差使相等概率很低。应判断两数之差是否落在 (-e, e) 内,e 应比浮点精度大一个数量级。


第 30 题:全局变量和局部变量有什么区别?怎么实现的?OS 和编译器怎么知道?

参考答案:生命周期不同(全局随主程序创建销毁,局部在函数/循环体内存在);内存位置不同(全局在全局数据区,程序开始时加载;局部在栈区)。OS 和编译器通过内存分配的位置来区分。


第 31 题:Heap 与 stack 的差别

参考答案:Stack(栈)由 OS 自动分配/释放,空间有限;Heap(堆)手动分配/释放,是很大的自由存储区。C 中 malloc 分配在堆上,C++ 对应 new。编译期变量和函数分配内存都在栈上,运行时函数调用参数传递也在栈上。


第 32 题:In C++, what does "explicit" mean? what does "protected" mean?

参考答案:explicit 修饰构造函数使其显式,要求使用者必须显式调用,防止默认类型转换造成预期外问题。protected 控制访问权限:只有该类的成员函数及其派生类的成员函数可访问。


第 33 题:重复多次 fclose 一个打开过一次的 FILE *fp 会有什么结果?

参考答案:导致文件描述符结构中指针指向的内存被重复释放,进而产生不可预期的异常。


第 34 题:为什么数组名作参数会改变数组内容,而 int 却不会?

参考答案:数组名作参数传递的是地址;int 作参数时是实参的一份拷贝,形参改变不影响实参。


第 35 题:不使用常量直接填数字/字符串,会有什么麻烦?

参考答案:1) 可读性变差,忘记数字含义;2) 多处重复输入易书写错误;3) 要修改时需多处改动,麻烦易错。


第 36 题:为什么需要使用堆?

参考答案:直到运行时才知道一个对象需要多少内存空间;不知道对象的生存期有多长。


第 37 题:const 关键字有哪些作用?

参考答案:

1) 阻止变量被改变,定义时需初始化;

2) 对指针可指定指针本身 const、所指数据 const 或二者皆 const;

3) 修饰形参表明是输入参数,函数内不能改其值;

4) 类成员函数为 const 时是常函数,不能改成员变量;

5) 成员函数返回值为 const 时使其返回值不为"左值"。


板块三:C++ 面向对象的特性(38--61)

第 38 题:父类写 virtual 函数,子类覆盖不加 virtual 也能实现多态吗?

参考答案:virtual 修饰符会被隐形继承,可加可不加。子类空间里有父类的所有变量(static 除外)。子类覆盖不加 virtual 也能实现多态。子类空间里有父类的私有变量,但私有变量不能直接访问。


第 39 题:面向对象的三个基本特征?

参考答案:

1) 封装:把客观事物抽象成类,对自身数据和方法实行 protection(private/protected/public);

2) 继承:分实现继承、可视继承、接口继承三种形式,构成功能复用的两种方式(类继承 + 对象组合/接口继承/纯虚函数);

3) 多态:允许将子类类型的指针赋值给父类类型的指针,父对象按赋给它的子对象特性以不同方式运作。


第 40 题:重载(overload)、重写(override)、重定义(redefinition)的区别?

标准答案

名称 名字空间 区别
重载 overload 同一名字空间 多个同名函数,参数表不同
重定义/隐藏 不同名字空间 继承中派生类与基类函数同名,屏蔽基类函数
重写/覆盖 不同名字空间 继承中,子类重新定义父类虚函数

第 41 题:多态的作用?

参考答案:

1) 隐藏实现细节,使代码模块化、扩展、重用;

2) 接口重用:继承和派生时保证使用家族中任一实例的属性时的正确调用。


第 42 题:类 A 中没有声明任何成员,sizeof(A) 是多少?为什么不为零?

标准答案:sizeof(A) = 1。编译器为每个对象分配至少一个字节以保证不同对象的地址不同。


第 43 题:ClassA 定义虚函数 func,ClassB 也实现,a->func() 调用哪个?如果不是虚函数呢?

参考答案:虚函数时调用 B 的;非虚函数时调用 A 的。虚函数只能借助指针或引用达到多态效果。


第 44 题:C++ 里是不是所有动作都是 main() 引起的?

参考答案:不是。全局变量的初始化就不是 main 引起的。

复制代码
class A {};
A a;        // a 的构造函数先执行
int main() {}

第 45 题:内联函数在编译时是否做参数类型检查?

参考答案:做,这是内联函数相对宏的优势。


第 46 题:请讲一讲析构函数和虚函数的用法和作用?

参考答案:析构函数是特殊成员函数,无返回类型、无参数、不能随意调用、无重载,只在对象生命期结束时由系统自动调用,有释放内存的作用。虚函数是 C++ 多态的表现,可灵活动态绑定,以一定开销为代价。


第 47 题:"new" in c++ is a:

A. library function like malloc in c B. key word C. operator D. none of the above

参考答案:C。malloc 是库函数不在编译器控制范围;new 是运算符在编译器控制范围。malloc 只从堆申请内存,new 从堆申请内存并为内存调用构造函数。


第 48 题:类(class)与结构(struct)描述正确的为:

A. 类成员默认 private,可声明 public/private/protected;结构成员默认 public

B. 结构不允许定义成员函数,类可以

C. 结构用 malloc 创建,类对象用 new 创建

D. 结构和类对象都必须用 new 创建

E. 结构不能定义虚函数,类可以

F. 结构不能有继承关系,类可以

标准答案:A、D


第 49 题:ClassA 中定义成员函数 AdditionalFunction(ClassA a, ClassB b),实现部分合法的表达式最全的是:

A. x.PrivateFunc(); x.PublicFunc(); y.PrivateFunc(); y.PublicFunc();

B. x.PrivateFunc(); x.PublicFunc(); y.PublicFunc();

C. x.PrivateFunc(); y.PrivateFunc(); y.PublicFunc();

D. x.PublicFunc(); y.PublicFunc();

标准答案:B(类内成员函数可访问同类对象的私有成员,但不能访问其它类的私有成员)


第 50 题:C++ 程序下列说法正确的有:

A. 对调用的虚函数和模板类都进行迟后编译

B. 基类与子类构成虚函数,除 virtual 声明外,必须名字、参数类型、返回类型相同

C. 重载的类成员函数必须返回类型不同,或参数数目不同,或参数序列类型不同

D. 静态成员函数和内联函数不能是虚函数,友员函数和构造函数也不能是虚函数,但析构函数可以是虚函数

标准答案:A


第 51 题:在 C++ 中有没有纯虚构造函数?

标准答案:构造函数不能是虚的,只能有虚的析构函数。


第 52 题:下面的 throw 表达式哪些是错误的?

复制代码
(a) class exceptionType { }; throw exceptionType {};
(b) enum mathErr { overflow, underflow, zeroDivide }; throw zeroDivide();

标准答案:修正为 throw exceptionType();throw zeroDivide;(对象加括号构造,枚举值直接抛)。


第 53 题:谈谈你是怎么认识 C++ 中的模板的?

参考答案:模板使程序员能够快速建立具有类型安全的类库集合和函数集合,方便了大规模软件开发(结合 STL 更好)。


第 54 题:在类中声明一个 static 成员变量有没有用?

参考答案:有用。static 成员变量为该类所有实例共享,不管创建多少对象只占一块内存;某个实例修改后其它所有实例可见。静态成员函数只能访问静态成员。static 是加了访问控制的全局变量,不被继承。


第 55 题:C++ 中为什么用模板类?

参考答案:

1) 可创建动态增长和减小的数据结构;

2) 类型无关,可复用性高;

3) 编译时检查数据类型,保证类型安全;

4) 平台无关,可移植;

5) 可用于基本数据类型。


第 56 题:函数模板与类模板有什么区别?

参考答案:函数模板的实例化由编译程序处理函数调用时自动完成;类模板的实例化必须由程序员显式指定。


第 58 题:请你谈谈你在类中如何使用 const 的。

参考答案:#define 宏常量是全局的,不能只在类内有效。const 数据成员确实存在,但只在某个对象生存期内是常量,对整个类而言可变(不同对象的 const 数据成员值可以不同)。不能在类声明中初始化 const 数据成员,只能在构造函数的初始化表中初始化。


第 59 题:函数重载靠什么区分调用的函数?靠返回值判断可不可以?

参考答案:同名函数参数不同(类型、顺序)容易区分。仅仅返回值类型不同,有时可以有时不能。例:

复制代码
void Function(void);
int  Function(void);

int x = Function(); 可判断是第二个,但 C++/C 程序中可忽略返回值,此时编译器和程序员都不知道哪个被调用。所以只能靠参数,不能靠返回值区分重载。


第 60 题:所有的运算符都能重载吗?

参考答案:不是。

1) 不能改变内部数据类型(int/float 等)的运算符;

2) 不能重载 .(对任何成员都有意义,已是标准用法);

3) 不能重载 C++ 中没有的符号(#、@、$ 等,难理解、难定优先级);

4) 重载时不能改变优先级规则。


第 61 题:基类析构函数不是虚函数会带来什么问题?

参考答案:派生类的析构函数用不上,会造成资源泄漏。


板块四:程序阅读题(62--90)

第 62 题:main 函数执行以前还会执行什么代码?

参考答案:全局对象的构造函数会在 main 之前执行。


第 63 题:不用 if/? :/switch 等判断语句,找出两个 int 变量中较大的一个。

标准答案:((a + b) + abs(a - b)) / 2


第 64 题:如何打印当前源文件的文件名和当前行号?

标准答案

复制代码
cout << __FILE__;
cout << __LINE__;

__FILE____LINE__ 是编译器定义的预定义宏(C 也有)。


第 65 题:if (n == 10)if (10 == n) 哪种更好?为什么?

参考答案:第二种更好。少写一个 = 时,10 = n 编译会报错,能检测出是否少了 =


第 66 题:写出运行结果

复制代码
{ // test1
    char str[] = "world"; cout << sizeof(str) << ": ";
    char *p = str; cout << sizeof(p) << ": ";
    char i = 10; cout << sizeof(i) << ": ";
    void *pp = malloc(10); cout << sizeof(p) << endl;
}

标准答案:6 : 4 : 1 : 4(数组含结尾 '\0' 为 6,指针 32 位下为 4)


第 67 题:不用第三方参数交换两个参数的值。

参考答案

复制代码
a = a + b;
b = a - b;
a = a - b;

第 68 题:以下代码如果有错,请改正,并写出输出结果?

复制代码
void main(void)
{
    int nArrLength(400), i = 546;
    for (int i = 0; i < 99999999999; i++);
    cout << nArrLength << endl;
    cout << i << endl;
}

标准答案:for 中的 i 是块作用域变量,循环后不存在,输出的是外部定义的 i;循环次数应改为 ~((int)0) 避免越界。输出:400546


第 69 题:int i = 5, b = 7; cout << (i+++b) << endl; 在 gcc 下的执行结果?

标准答案:12(i++ + b 先取 i 原值 5:5+7=12,再自增)


第 70 题:写一个能做左值的函数,如 max(x, y) += 2874 + 55;

参考答案

复制代码
int &max(int &x, int &y)
{
    return x > y ? x : y;
}
int x = 55, y = 77;
max(x, y) += 12 + 11;   // 此时 y = 92
cout << "x = " << x << "; y = " << y << endl;  // x = 55; y = 92

第 72 题:以下函数有什么错误,改正:

复制代码
int add_n(int n)
{
    static int i = 100;
    i += n;
    return i;
}

标准答案:static 使 i 保留上次的值并一直更新,第二次调用出错。去掉 static 即可。


第 73 题:写出打印结果

复制代码
unsigned short array[] = {1,2,3,4,5,6,7};
int i = 3;
*(array + i) = ?

标准答案:4


第 74 题:写函数计算 1-2+3-4+5-6+7......+n(n 很大)。

参考答案

复制代码
long fn(long n)
{
    if (n <= 0) { printf("error: n must > 0"); exit(1); }
    if (0 == n % 2) return (n / 2) * (-1);
    else return (n / 2) * (-1) + n;
}

第 75 题:字符指针、浮点数指针、函数指针哪个占内存最大?为什么?

参考答案:所有指针变量占用内存字节数相同(足够表示最大地址,通常是一个机器字长),与指向何种对象无关。


第 76 题:以下三条输出语句分别输出什么?

复制代码
char str1[] = "abc"; char str2[] = "abc";
const char str3[] = "abc"; const char str4[] = "abc";
const char* str5 = "abc"; const char* str6 = "abc";
cout << boolalpha << (str1 == str2) << endl;
cout << boolalpha << (str3 == str4) << endl;
cout << boolalpha << (str5 == str6) << endl;

参考答案:false, false, true。str1/str2 是字符数组各有存储区,比较的是各自首地址,不等;str3/str4 同理;str5/str6 是字符指针不分配存储区,"abc" 以常量存于静态数据区,指针都指向该区首地址,相等。


第 77 题:以下代码有什么问题?

复制代码
cout << (true ? 1 : "1") << endl;

参考答案:三元表达式 ?: 的两个操作数必须为同一类型。


第 78 题:以下代码能编译通过吗?为什么?

复制代码
unsigned int const size1 = 2;
char str1[size1];
unsigned int temp = 0; cin >> temp;
unsigned int const size2 = temp;
char str2[size2];

标准答案:str2 定义出错。size2 非编译期常量,数组长度要求编译期常量。


第 79 题:以下代码输出 0 吗?为什么?

复制代码
struct CLS {
    int m_i;
    CLS(int i) : m_i(i) {}
    CLS() { CLS(0); }
};
CLS obj;
cout << obj.m_i << endl;

标准答案:不能(不会输出 0)。默认构造函数内部再调用带参构造函数属于用户行为而非编译器行为,仅执行函数调用,不执行其后的初始化表达式。


第 80 题:How do you code an infinite loop in C++?

参考答案:while(1) {}for(;;) {}


第 81 题:What are the values of a, b, and c after: int a=5, b=7, c; c = a+++b;

标准答案:a = 6, b = 7, c = 12


第 82 题:排序方法中,关键码比较次数与记录初始排列无关的是( )

A. Shell 排序 B. 归并排序 C. 直接插入排序 D. 选择排序

标准答案:D


第 83 题:static int val; 的内存地址位于:

A. 已初始化数据段 B. 未初始化数据段 C. 堆 D. 栈

标准答案:A(静态变量自动初始化为 0,属已初始化数据段)


第 84 题:入栈序列 A、B、C、D、E,栈的不可能输出序列是( )

A. EDCBA B. DECBA C. DCEAB D. ABCDE

标准答案:C


第 85 题:判断 ABCD 四个表达式是否正确,若正确写出 a 的值。

复制代码
int a = 4;
(A) a += (a++);
(B) a += (++a);
(C) (a++) += a;
(D) (++a) += (a++);

参考答案:C 错误(左侧不是有效变量),可改为 (++a) += a;。改后答案依次为 9、10、10、11。


第 86 题:你是如何使用 return 语句的?

参考答案:

1) 不可返回指向"栈内存"的"指针"或"引用"(函数结束时被自动销毁);

2) 搞清返回的是"值"、"指针"还是"引用";

3) 返回值是对象时要考虑 return 的效率。


第 87 题:return String(s1 + s2);String temp(s1 + s2); return temp; 一样吗?

参考答案:不一样。

① 创建临时对象并返回,编译器直接把临时对象创建并初始化在外部存储单元中,省去拷贝和析构开销,效率高;

② 发生三件事:创建 temp → 拷贝构造函数拷到外部存储单元 → temp 结束被销毁。


第 88 题:下列程序的运行结果

复制代码
const char *str = "vermeer";
int main() {
    const char *pstr = str;
    cout << "The address of pstr is: " << pstr << endl;
}

标准答案:The address of pstr is: vermeer(输出 const char* 时输出字符串内容)


第 89 题:下列程序输出结果

复制代码
inline void max_out(int val1, int val2)
{
    cout << (val1 > val2) ? val1 : val2;
}
int main() {
    int ix = 10, jx = 20;
    cout << "The larger of " << ix;
    cout << ", " << jx << " is ";
    max_out(ix, jx);
    cout << endl;
}

标准答案:The larger of 10, 20 is 0。因为输出操作符 << 优先级高于条件操作符,先输出 (val1 > val2) 的布尔结果(false 为 0)。


第 90 题:

复制代码
int max(int *ia, int sz);
int max(int *, int = 10);

算函数重载?还是重复声明?

标准答案:如果两个函数参数表只有缺省实参不同,第二个声明被视为第一个的重复声明。


板块五:编程练习(91--100)

第 91 题:编写一个 C 函数,给出一个字节中被置 1 的位的个数。

参考答案

复制代码
unsigned int TestAsOne0(char log)
{
    int i;
    unsigned int num = 0, val;
    for (i = 0; i < 8; i++) {
        val = log >> i;      // 移位
        val &= 0x01;         // 与 1 相与
        if (val) num++;
    }
    return num;
}

第 92 题:编写函数,把十六进制数组成的字符串转换成十进制数字并返回。

参考答案

复制代码
BOOL HexToDec(LPCTSTR shex, int &idec)
{
    int i, mid;
    int len = lstrlen(shex);
    if (len > 8) return FALSE;
    mid = 0; idec = 0;
    for (i = 0; i < len; i++) {
        if (shex[i] >= '0' && shex[i] <= '9') mid = shex[i] - '0';
        else if (shex[i] >= 'a' && shex[i] <= 'f') mid = shex[i] - 'a' + 10;
        else if (shex[i] >= 'A' && shex[i] <= 'F') mid = shex[i] - 'A' + 10;
        else return FALSE;
        mid <<= ((len - i - 1) << 2);   // 移位表示变为 2 的 n 次方倍
        idec = idec + mid;
    }
    return TRUE;
}

第 93 题:输入一个字符串,将其逆序后输出。

参考答案

复制代码
void main()
{
    char a[50]; memset(a, 0, sizeof(a));
    int i = 0, j;
    char t;
    cin.getline(a, 50, '\n');
    for (i = 0, j = strlen(a) - 1; i < strlen(a) / 2; i++, j--) {
        t = a[i]; a[i] = a[j]; a[j] = t;
    }
    cout << a << endl;
}

第 94 题:编写算法 frequency,统计输入字符串中各个不同字符出现的频度。

参考答案

复制代码
void frequency(String &s, char A[], int C[], int &k)
{
    int i, j, len = s.length();
    if (!len) { cout << "The string is empty. " << endl; k = 0; return; }
    A[0] = s[0]; C[0] = 1; k = 1;
    for (i = 1; i < len; i++) C[i] = 0;          // 初始化
    for (i = 1; i < len; i++) {                  // 检测串中所有字符
        j = 0;
        while (j < k && A[j] != s[i]) j++;       // 检查 s[i] 是否已在 A[] 中
        if (j == k) { A[k] = s[i]; C[k]++; k++; } // s[i] 从未检测过
        else C[j]++;                              // s[i] 已经检测过
    }
}

第 95 题:循环队列,给出队空/队满条件,写出插入和删除操作。

参考答案

复制代码
#include <assert.h>
template <class Type> class Queue {   // 循环队列的类定义
public:
    Queue(int = 10);
    ~Queue() { delete[] elements; }
    void EnQueue(Type &item);
    Type DeQueue();
    Type GetFront();
    void MakeEmpty() { length = 0; }                    // 置空队列
    int IsEmpty() const { return length == 0; }         // 判队列空
    int IsFull() const { return length == maxSize; }    // 判队列满
private:
    int rear, length;     // 队尾指针和队列长度
    Type *elements;       // 存放队列元素的数组
    int maxSize;          // 队列最大可容纳元素个数
};

template <class Type>
Queue<Type>::Queue(int sz) : rear(maxSize - 1), length(0), maxSize(sz)
{
    elements = new Type[maxSize];
    assert(elements != 0);
}

template <class Type>
void Queue<Type>::EnQueue(Type &item)
{
    assert(!IsFull());
    length++;
    rear = (rear + 1) % maxSize;
    elements[rear] = item;
}

template <class Type>
Type Queue<Type>::DeQueue()
{
    assert(!IsEmpty());
    length--;
    return elements[(rear - length + maxSize) % maxSize];  // 返回原队头元素值
}

template <class Type>
Type Queue<Type>::GetFront()
{
    assert(!IsEmpty());
    return elements[(rear - length + 1 + maxSize) % maxSize];
}

第 96 题:数组递归算法:求最大值、和、平均值。

参考答案

复制代码
class RecurveArray {
private:
    int *Elements; int ArraySize; int CurrentSize;
public:
    RecurveArray(int MaxSize = 10) : ArraySize(MaxSize), Elements(new int[MaxSize]) {}
    ~RecurveArray() { delete[] Elements; }
    void InputArray();
    int MaxKey(int n);      // 求最大值
    int Sum(int n);         // 求数组元素之和
    float Average(int n);   // 求平均值
};

int RecurveArray::MaxKey(int n) {
    if (n == 1) return Elements[0];
    int temp = MaxKey(n - 1);
    if (Elements[n-1] > temp) return Elements[n-1];
    else return temp;
}

int RecurveArray::Sum(int n) {
    if (n == 1) return Elements[0];
    else return Elements[n-1] + Sum(n - 1);
}

float RecurveArray::Average(int n) {
    if (n == 1) return (float)Elements[0];
    else return ((float)Elements[n-1] + (n - 1) * Average(n - 1)) / n;
}

第 97 题:链表递归算法:求最大值、结点个数、平均值。

参考答案

复制代码
class ListNode {
    friend class List;
private:
    int data; ListNode *link;
    ListNode(const int item) : data(item), link(NULL) {}
};

class List {
private:
    ListNode *first, *current;
    int Max(ListNode *f);
    int Num(ListNode *f);
    float Avg(ListNode *f, int &n);
public:
    List() : first(NULL), current(NULL) {}
    int GetMax() { return Max(first); }
    int GetNum() { return Num(first); }
    float GetAvg() { return Avg(first, n); }
};

int List::Max(ListNode *f) {
    if (f->link == NULL) return f->data;
    int temp = Max(f->link);
    if (f->data > temp) return f->data;
    else return temp;
}

int List::Num(ListNode *f) {
    if (f == NULL) return 0;
    return 1 + Num(f->link);
}

float List::Avg(ListNode *f, int &n) {
    if (f->link == NULL) { n = 1; return (float)(f->data); }
    else {
        float Sum = Avg(f->link, n) * n;
        n++;
        return (f->data + Sum) / n;
    }
}

第 98 题:字符串替换操作 replace(用 v 替换 t 在 s 中的所有出现)。

参考答案

复制代码
String &String::Replace(String &t, String &v)
{
    if ((int id = Find(t)) == -1) {   // 没有找到则返回
        cout << "The (replace) operation failed." << endl;
        return *this;
    }
    String temp(ch);
    ch[0] = '\0'; curLen = 0;
    int j, k = 0, l;
    while (id != -1) {
        for (j = 0; j < id; j++) ch[k++] = temp.ch[j];
        curLen += id + v.curLen;
        if (curLen <= maxLen) l = v.curLen;
        else { l = curLen - maxLen; curLen = maxLen; }
        for (j = 0; j < l; j++) ch[k++] = v.ch[j];
        if (curLen == maxLen) break;
        for (j = id + t.curLen; j < temp.curLen; j++)
            temp.ch[j - id - t.curLen] = temp.ch[j];
        temp.curLen -= (id + t.curLen);
        id = temp.Find(t);
    }
    return *this;
}

第 99 题:求解 Josephus 问题(n=9, s=1, m=5 / m=0 / m=10 验证健壮性)。

参考答案

复制代码
void Josephus(int A[], int n, int s, int m)
{
    int i, j, k, tmp;
    if (m == 0) { cout << "m = 0是无效的参数!" << endl; return; }
    for (i = 0; i < n; i++) A[i] = i + 1;   // 初始化
    i = s - 1;
    for (k = n; k > 1; i--) {               // 逐个出局
        if (i == k) i = 0;
        i = (i + m - 1) % k;                // 寻找出局位置
        if (i != k - 1) {
            tmp = A[i];
            for (j = i; j < k - 1; j++) A[j] = A[j+1];
            A[k-1] = tmp;
        }
    }
    for (k = 0; k < n / 2; k++) {           // 逆置得到出局序列
        tmp = A[k]; A[k] = A[n-k+1]; A[n-k+1] = tmp;
    }
}

第 100 题:编写类 String 的构造函数、析构函数和赋值函数。

参考答案

复制代码
// 析构函数
String::~String(void)
{
    delete[] m_data;
}

// 普通构造函数
String::String(const char *str)
{
    if (str == NULL) {
        m_data = new char[1];
        *m_data = '\0';
    } else {
        int length = strlen(str);
        m_data = new char[length + 1];
        strcpy(m_data, str);
    }
}

// 拷贝构造函数
String::String(const String &other)
{
    int length = strlen(other.m_data);
    m_data = new char[length + 1];
    strcpy(m_data, other.m_data);
}

// 赋值函数
String &String::operator=(const String &other)
{
    if (this == &other) return *this;
    delete[] m_data;
    int length = strlen(other.m_data);
    m_data = new char[length + 1];
    strcpy(m_data, other.m_data);
    return *this;
}

相关推荐
汉克老师14 分钟前
CSP-J 初赛(以满分为目标):第十六课 《STL容器与常见数据结构——C++自带的“数据结构工具箱”》
c++·csp-j·小学生·学c++编程
动词ing15 分钟前
【学习笔记】字符串(遍历+反转+替换+子串匹配+KMP)+题目解析
学习·算法
Freak嵌入式21 分钟前
告别死循环!Pico 外部中断控制 LED,比轮询高效 100 倍
java·开发语言·stm32·单片机·嵌入式硬件
nangonghen22 分钟前
Agent如何传递不同类型的ID给MCP Server
开发语言·python
大模型码小白25 分钟前
MCP协议开发实战:从零搭建AI Agent工具链
运维·人工智能·算法·机器学习·自动化
luj_176834 分钟前
断舍离中的项目管理智慧
c语言·开发语言·c++·经验分享·算法
FFZero135 分钟前
[mpv架构] (三) mpv 怎么实现 MP4 秒开?
c++·音视频·mpv
老王爱玩车39 分钟前
关于函数递归的优缺点分析
开发语言·数据结构·学习·算法
无限码力1 小时前
拼多多 春招&秋招 笔试真题题库目录|笔试题库 + 算法考点详解
算法·pdd笔试真题·pdd笔试真题题解·拼多多春招笔试真题·拼多多秋招笔试真题·拼多多笔试真题题解