华为C++笔试题及答案

C语言和C++笔试题及答案集锦(已排版)
1. 在什么时候需要使用“常引用”?
如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使
用常引用。常引用声明方式:const 类型标识符 &引用名=目标变量名;
例 1
int a ;
const int &ra=a;
ra=1; //错误
a=1; //正确
例 2
string foo( );
void bar(string & s);
那么下面的表达式将是非法的:
bar(foo( ));
bar("hello world");
原因在于 foo( )和"hello world"串都会产生一个临时对象,而在 C++中,这些临时对象都是
const 类型的。因此上面的表达式就是试图将一个 const 类型的对象转换为非 const 类型,这
是非法的。
引用型参数应该在能被定义为 const的情况下,尽量定义为 const。
2.求下面函数的返回值(微软)
int func(x)
{
int countx = 0;
while(x)
{
countx ++;
x = x&(x-1);
}
return countx;
}
假定 x = 9999。 答案:8
思路:将 x转化为 2 进制,看含有的 1 的个数。

3. 什么是“引用”?申明和使用“引用”要注意哪些问题?
答:引用就是某个目标变量的“别名”(alias),对引用的操作与对变量直接操作效果完全相
同。申明一个引用的时候,切记要对其进行初始化。引用声明完毕后,相当于目标变量名有
两个名称,即该目标原名称和引用名,不能再把该引用名作为其他变量名的别名。声明一个
引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一
种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。不能建立数组的
引用。

4. 将“引用”作为函数参数有哪些特点?
(1)传递引用给函数与传递指针的效果是一样的。这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其
相应的目标对象(在主调函数中)的操作。
(2)使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;
而使用一般变量传递函数的参数,当发生函数调用时,需要给形参分配存储单元,形参变量
是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。因此,当参数传递的数据
较大时,用引用比用一般变量传递参数的效率和所占空间都好。
(3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样
要给形参分配存储单元,且需要重复使用"*指针变量名"的形式进行运算,这很容易产生错
误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。
而引用更容易使用,更清晰。

5. 将“引用”作为函数返回值类型的格式、好处和需要遵守的规则?
格式:类型标识符 &函数名(形参列表及类型说明){ //函数体 }
好处:在内存中不产生被返回值的副本;(注意:正是因为这点原因,所以返回一个局部变
量的引用是不可取的。因为随着该局部变量生存期的结束,相应的引用也会失效,产生
runtime error!
注意事项:
(1)不能返回局部变量的引用。这条可以参照 Effective C++[1]的 Item 31。主要原因是局部
变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知
状态。
(2)不能返回函数内部 new分配的内存的引用。这条可以参照 Effective C++[1]的 Item 31。
虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部 new 分配内存的引
用),又面临其它尴尬局面。例如,被函数返回的引用只是作为一个临时变量出现,而没有
被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放,造成memory
leak。
(3)可以返回类成员的引用,但最好是 const。这条原则可以参照 Effective C++[1]的 Item 30。
主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值常常与
某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果
其它对象可以获得该属性的非常量引用(或指针),那么对该属性的单纯赋值就会破坏业务
规则的完整性。
(4)流操作符重载返回值申明为“引用”的作用:
流操作符<<和>>,这两个操作符常常希望被连续使用,例如:cout << "hello" << endl; 因此
这两个操作符的返回值应该是一个仍然支持这两个操作符的流引用。可选的其它方案包括:
返回一个流对象和返回一个流对象指针。但是对于返回一个流对象,程序必须重新(拷贝)
构造一个新的流对象,也就是说,连续的两个<<操作符实际上是针对不同对象的!这无法
让人接受。对于返回一个流指针则不能连续使用<<操作符。因此,返回一个流对象引用是
惟一选择。这个唯一选择很关键,它说明了引用的重要性以及无可替代性,也许这就是 C++
语言中引入引用这个概念的原因吧。赋值操作符=。这个操作符象流操作符一样,是可以连
续使用的,例如:x = j = 10;或者(x=10)=100;赋值操作符的返回值必须是一个左值,以便可
以被继续赋值。因此引用成了这个操作符的惟一返回值选择。
例 3
#i nclude
int &put(int n);
int vals[10]; int error=-1;
void main()
{
put(0)=10; //以 put(0)函数值作为左值,等价于 vals[0]=10;
put(9)=20; //以 put(9)函数值作为左值,等价于 vals[9]=20;
cout<cout<}
int &put(int n)
{
if (n>=0 && n<=9 ) return vals[n];
else { cout<<"subscript error"; return error; }
}
(5)在另外的一些操作符中,却千万不能返回引用:+-*/ 四则运算符。它们不能返回引用,
Effective C++[1]的Item23 详细的讨论了这个问题。主要原因是这四个操作符没有side effect,
因此,它们必须构造一个对象作为返回值,可选的方案包括:返回一个对象、返回一个局部
变量的引用,返回一个 new 分配的对象的引用、返回一个静态对象引用。根据前面提到的
引用作为返回值的三个规则,第 2、3 两个方案都被否决了。静态对象的引用又因为((a+b) ==
(c+d))会永远为 true 而导致错误。所以可选的只剩下返回一个对象了。

6. “引用”与多态的关系?
引用是除指针外另一个可以产生多态效果的手段。这意味着,一个基类的引用可以指向它的
派生类实例。
例 4
Class A; Class B : Class A{...}; B b; A& ref = b;

7. “引用”与指针的区别是什么?
指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程
序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。此
外,就是上面提到的对函数传 ref 和 pointer 的区别。

8. 什么时候需要“引用”?
流操作符<<和>>、赋值操作符=的返回值、拷贝构造函数的参数、赋值操作符=的参数、其
它情况都推荐使用引用。
以上 2-8 参考:http://blog.csdn.net/wfwd/archive/2006/05/30/763551.aspx

9. 结构与联合有何区别?
1. 结构和联合都是由多个不同的数据类型成员组成, 但在任何同一时刻, 联合中只存放了
一个被选中的成员(所有成员共用一块地址空间), 而结构的所有成员都存在(不同成员的
存放地址不同)。
2. 对于联合的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于结构
的不同成员赋值是互不影响的。

10. 写出下面关于“联合”的题目的输出? a)
#i nclude
union
{
int i;
char x[2];
}a;

void main()
{
a.x[0] = 10;
a.x[1] = 1;
printf("%d",a.i);
}
答案:266 (低位低地址,高位高地址,内存占用情况是 Ox010A)
b)
main()
{
union{ /*定义一个联合*/
int i;
struct{ /*在联合中定义一个结构*/
char first;
char second;
}half;
}number;
number.i=0x4241; /*联合成员赋值*/
printf("%c%c\n", number.half.first, mumber.half.second);
number.half.first='a'; /*联合中结构成员赋值*/
number.half.second='b';
printf("%x\n", number.i);
getch();
}
答案: AB (0x41 对应'A',是低位;Ox42 对应'B',是高位)
6261 (number.i 和 number.half共用一块地址空间)

11. 已知strcpy的函数原型:char *strcpy(char *strDest, const char *strSrc)其中strDest 是目
的字符串,strSrc 是源字符串。不调用C++/C 的字符串库函数,请编写函数 strcpy。
答案:
char *strcpy(char *strDest, const char *strSrc)
{
if ( strDest == NULL || strSrc == NULL)
return NULL ;
if ( strDest == strSrc)
return strDest ; char *tempptr = strDest ;
while( (*strDest++ = *strSrc++) != ‘\0’)
;
return tempptr ;
}

12. 已知String类定义如下:
class String
{
public:
String(const char *str = NULL); // 通用构造函数
String(const String &another); // 拷贝构造函数
~ String(); // 析构函数
String & operater =(const String &rhs); // 赋值函数
private:
char *m_data; // 用于保存字符串
};
尝试写出类的成员函数实现。
答案:
String::String(const char *str)
{
if ( str == NULL ) //strlen 在参数为 NULL 时会抛异常才会有这步判断
{
m_data = new char[1] ;
m_data[0] = '\0' ;
}
else
{
m_data = new char[strlen(str) + 1];
strcpy(m_data,str);
}
}
String::String(const String &another)
{
m_data = new char[strlen(another.m_data) + 1];
strcpy(m_data,other.m_data);
}

String& String::operator =(const String &rhs)
{
if ( this == &rhs)
return *this ;
delete []m_data; //删除原来的数据,新开一块内存
m_data = new char[strlen(rhs.m_data) + 1]; strcpy(m_data,rhs.m_data);
return *this ;
}

String::~String()
{
delete []m_data ;
}

13. .h头文件中的ifndef/define/endif 的作用?
答:防止该头文件被重复引用。

14. #i nclude 与 #i nclude "file.h"的区别?
答:前者是从 Standard Library的路径寻找和引用 file.h,而后者是从当前工作路径搜寻并引
用 file.h。

15.在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern “C”?
首先,作为 extern 是 C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关
键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。
通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字 extern
声明。例如,如果模块 B 欲引用该模块 A中定义的全局变量和函数时只需包含模块 A的头
文件即可。这样,模块 B 中调用模块 A中的函数时,在编译阶段,模块 B 虽然找不到该函
数,但是并不会报错;它会在连接阶段中从模块 A编译生成的目标代码中找到此函数
extern "C"是连接申明(linkage declaration),被extern "C"修饰的变量和函数是按照 C 语言方式
编译和连接的,来看看 C++中对类似 C的函数是怎样编译的:
作为一种面向对象的语言,C++支持函数重载,而过程式语言 C 则不支持。函数被 C++编译
后在符号库中的名字与 C 语言的不同。例如,假设某个函数的原型为:
void foo( int x, int y );
该函数被 C 编译器编译后在符号库中的名字为_foo,而 C++编译器则会产生像_foo_int_int
之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字
称为“mangled name”)。
_foo_int_int 这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来
实现函数重载的。例如,在 C++中,函数 void foo( int x, int y )与 void foo( int x, float y )编译
生成的符号是不相同的,后者为_foo_int_float。
同样地,C++中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序
的类成员变量可能与全局变量同名,我们以"."来区分。而本质上,编译器在进行编译时,
与函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名
的全局变量名字不同。
未加 extern "C"声明时的连接方式
假设在 C++中,模块 A的头文件如下:
// 模块 A头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
int foo( int x, int y ); #endif
在模块 B 中引用该函数:
// 模块 B 实现文件 moduleB.cpp
#i nclude "moduleA.h"
foo(2,3);
实际上,在连接阶段,连接器会从模块 A 生成的目标文件 moduleA.obj 中寻找_foo_int_int
这样的符号!
加 extern "C"声明后的编译和连接方式
加 extern "C"声明后,模块 A的头文件变为:
// 模块 A头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
extern "C" int foo( int x, int y );
#endif
在模块 B 的实现文件中仍然调用 foo( 2,3 ),其结果是:
(1)模块 A编译生成 foo的目标代码时,没有对其名字进行特殊处理,采用了 C 语言的方
式;
(2)连接器在为模块 B的目标代码寻找 foo(2,3)调用时,寻找的是未经修改的符号名_foo。
如果在模块 A中函数声明了 foo为 extern "C"类型,而模块 B 中包含的是 extern int foo( int x,
int y ) ,则模块 B 找不到模块 A中的函数;反之亦然。
所以,可以用一句话概括 extern “C”这个声明的真实目的(任何语言中的任何语法特性的
诞生都不是随意而为的,来源于真实世界的需求驱动。我们在思考问题时,不能只停留在这
个语言是怎么做的,还要问一问它为什么要这么做,动机是什么,这样我们可以更深入地理
解许多问题):实现 C++与 C 及其它语言的混合编程。
明白了 C++中 extern "C"的设立动机,我们下面来具体分析 extern "C"通常的使用技巧:
extern "C"的惯用法
(1)在 C++中引用 C 语言中的函数和变量,在包含 C 语言头文件(假设为 cExample.h)时,
需进行下列处理:
extern "C"
{
#i nclude "cExample.h"
}
而在 C 语言的头文件中,对其外部函数只能指定为 extern类型,C 语言中不支持 extern "C"
声明,在.c文件中包含了 extern "C"时会出现编译语法错误。
C++引用C函数例子工程中包含的三个文件的源代码如下:
/* c 语言头文件:cExample.h */
#ifndef C_EXAMPLE_H
#define C_EXAMPLE_H
extern int add(int x,int y);
#endif

/* c 语言实现文件:cExample.c */
#i nclude "cExample.h"
int add( int x, int y ) {
return x + y;
}

// c++实现文件,调用 add:cppFile.cpp
extern "C"
{
#i nclude "cExample.h"
}
int main(int argc, char* argv[])
{
add(2,3);
return 0;
}
如果 C++调用一个 C 语言编写的.DLL 时,当包括.DLL 的头文件或声明接口函数时,应加
extern "C" { }。
(2)在 C 中引用 C++语言中的函数和变量时,C++的头文件需添加 extern "C",但是在 C
语言中不能直接引用声明了extern "C"的该头文件,应该仅将C文件中将C++中定义的extern
"C"函数声明为 extern 类型。
C 引用 C++函数例子工程中包含的三个文件的源代码如下:
//C++头文件 cppExample.h
#ifndef CPP_EXAMPLE_H
#define CPP_EXAMPLE_H
extern "C" int add( int x, int y );
#endif

//C++实现文件 cppExample.cpp
#i nclude "cppExample.h"
int add( int x, int y )
{
return x + y;
}

/* C 实现文件 cFile.c */
/* 这样会编译出错:#i nclude "cExample.h" */
extern int add( int x, int y );
int main( int argc, char* argv[] )
{
add( 2, 3 );
return 0;
}
15 题目的解答请参考《C++中 extern“C”含义深层探索》注解。

16. 关联、聚合(Aggregation)以及组合(Composition)的区别? 涉及到 UML中的一些概念:关联是表示两个类的一般性联系,比如“学生”和“老师”就
是一种关联关系;聚合表示 has-a 的关系,是一种相对松散的关系,聚合类不需要对被聚合
类负责,如下图所示,用空的菱形表示聚合关系:
从实现的角度讲,聚合可以表示为:
class A {...} class B { A* a; .....}
而组合表示 contains-a 的关系,关联性强于聚合:组合类与被组合类有相同的生命周期,组
合类要对被组合类负责,采用实心的菱形表示组合关系:
实现的形式是:
class A{...} class B{ A a; ...}
参考文章:1) http://blog.csdn.net/wfwd/archive/2006/05/30/763753.aspx
2) http://blog.csdn.net/wfwd/archive/2006/05/30/763760.aspx

17.面向对象的三个基本特征,并简单叙述之?
1. 封装:将客观事物抽象成类,每个类对自身的数据和方法实行 protection(private,
protected,public)
2. 继承:广义的继承有三种实现形式:实现继承(指使用基类的属性和方法而无需额外编
码的能力)、可视继承(子窗体使用父窗体的外观和实现代码)、接口继承(仅使用属性和方
法,实现滞后到子类实现)。前两种(类继承)和后一种(对象组合=>接口继承以及纯虚函
数)构成了功能复用的两种方式。
3. 多态:是将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象
就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许
将子类类型的指针赋值给父类类型的指针。

18. 重载(overload)和重写(overried,有的书也叫做“覆盖”)的区别?
常考的题目。从定义上来说:
重载:是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参
数类型不同,或许两者都不同)。
重写:是指子类重新定义复类虚函数的方法。
从实现原理上来说:
重载:编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了
不同的函 数 ( 至 少 对 于 编 译 器 来 说 是 这 样 的 )。 如 , 有 两 个 同 名 函 数 :function
func(p:integer):integer;和 function func(p:string):integer;。那么编译器做过修饰后的函数名称可
能是这样的:int_func、str_func。对于这两个函数的调用,在编译器间就已经确定了,是静
态的。也就是说,它们的地址在编译期就绑定了(早绑定),因此,重载和多态无关!
重写:和多态真正相关。当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的
子类指针,动态的调用属于子类的该函数,这样的函数调用在编译期间是无法确定的(调用
的子类的虚函数的地址无法给出)。因此,这样的函数地址是在运行期绑定的(晚绑定)。

19. 多态的作用?
主要是两个:1. 隐藏实现细节,使得代码能够模块化;扩展代码模块,实现代码重用;2. 接
口重用:为了类在继承和派生的时候,保证使用家族中任一类的实例的某一属性时的正确调
用。

20. Ado与Ado.net的相同与不同? 除了“能够让应用程序处理存储于 DBMS 中的数据“这一基本相似点外,两者没有太多共
同之处。但是 Ado 使用OLE DB 接口并基于微软的 COM 技术,而 ADO.NET 拥有自己的
ADO.NET 接口并且基于微软的.NET 体系架构。众所周知.NET 体系不同于 COM 体系,
ADO.NET 接口也就完全不同于 ADO 和 OLE DB 接口,这也就是说 ADO.NET 和 ADO是
两种数据访问方式。ADO.net 提供对 XML 的支持。

21. new delete 与malloc free 的联系与区别?
答案:都是在堆(heap)上进行动态的内存操作。用 malloc 函数需要指定内存分配的字节数并
且不能初始化对象,new 会自动调用对象的构造函数。delete 会调用对象的 destructor,而
free 不会调用对象的 destructor.

22. #define DOUBLE(x) x+x ,i = 5*DOUBLE(5); i 是多少?
答案:i 为30。

23. 有哪几种情况只能用intialization list 而不能用assignment?
答案:当类中含有 const、reference 成员变量;基类的构造函数都需要初始化表。

24. C++是不是类型安全的?
答案:不是。两个不同类型的指针之间可以强制转换(用 reinterpret cast)。C#是类型安全的。

25. main 函数执行以前,还会执行什么代码?
答案:全局对象的构造函数会在 main 函数之前执行。

26. 描述内存分配方式以及它们的区别?
1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运
行期间都存在。例如全局变量,static 变量。
2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行
结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。
3) 从堆上分配,亦称动态内存分配。程序在运行的时候用 malloc 或new 申请任意多少的
内存,程序员自己负责在何时用 free 或 delete 释放内存。动态内存的生存期由程序员决定,
使用非常灵活,但问题也最多。

27.struct 和 class 的区别
答案:struct 的成员默认是公有的,而类的成员默认是私有的。struct 和 class 在其他方面
是功能相当的。
从感情上讲,大多数的开发者感到类和结构有很大的差别。感觉上结构仅仅象一堆缺乏封装
和功能的开放的内存位,而类就象活的并且可靠的社会成员,它有智能服务,有牢固的封装
屏障和一个良好定义的接口。既然大多数人都这么认为,那么只有在你的类有很少的方法并
且有公有数据(这种事情在良好设计的系统中是存在的!)时,你也许应该使用 struct 关键
字,否则,你应该使用 class 关键字。

28.当一个类A 中没有声明任何成员变量与成员函数,这时sizeof(A)的值是多少,如果不是
零,请解释一下编译器为什么没有让它为零。(Autodesk)
答案:肯定不是零。举个反例,如果是零的话,声明一个 class A[10]对象数组,而每一个对象占用的空间是零,这时就没办法区分 A[0],A[1]…了。
29. 在 8086 汇编下,逻辑地址和物理地址是怎样转换的?(Intel)
答案:通用寄存器给出的地址,是段内偏移地址,相应段寄存器地址*10H+通用寄存器内地
址,就得到了真正要访问的地址。

30. 比较C++中的 4种类型转换方式?
重点是 static_cast, dynamic_cast 和 reinterpret_cast 的区别和应用。
请参考:http://blog.csdn.net/wfwd/archive/2006/05/30/763785.aspx

31.分别写出BOOL,int,float,指针类型的变量a 与“零”的比较语句。
答案:
BOOL : if ( !a ) or if(a)
int : if ( a == 0)
float : const EXPRESSION EXP = 0.000001
if ( a < EXP && a >-EXP)
pointer : if ( a != NULL) or if(a == NULL)

32.请说出const与#define 相比,有何优点?
答案:1) const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安
全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不
到的错误。
2) 有些集成化的调试工具可以对 const 常量进行调试,但是不能对宏常量进行调试。

33.简述数组与指针的区别?
数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。指针可以随时指向任意
类型的内存块。
(1)修改内容上的差别
char a[] = “hello”;
a[0] = ‘X’;
char *p = “world”; // 注意 p 指向常量字符串
p[0] = ‘X’; // 编译器不能发现该错误,运行时错误
(2) 用运算符 sizeof 可以计算出数组的容量(字节数)。sizeof(p),p 为指针得到的是一个指
针变量的字节数,而不是 p 所指的内存容量。C++/C 语言没有办法知道指针所指的内存容
量,除非在申请内存时记住它。注意当数组作为函数的参数进行传递时,该数组自动退化为
同类型的指针。
char a[] = "hello world";
char *p = a;
cout<< sizeof(a) << endl; // 12 字节
cout<< sizeof(p) << endl; // 4 字节
计算数组和指针的内存容量
void Func(char a[100])
{
cout<< sizeof(a) << endl; // 4 字节而不是 100 字节
}
34.类成员函数的重载、覆盖和隐藏区别?
答案:
a.成员函数被重载的特征:
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
b.覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有 virtual 关键字。
c.“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无 virtual关键字,
基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有 virtual 关
键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。

35. There are two int variables: a and b, don’t use “if”, “? :”, “switch”or other judgement
statements, find out the biggest one of the two numbers.
答案:( ( a + b ) + abs( a - b ) ) / 2

36. 如何打印出当前源文件的文件名以及源文件的当前行号?
答案:
cout << __FILE__ ;
cout<<__LINE__ ;
__FILE__和__LINE__是系统预定义宏,这种宏并不是在某个文件中定义的,而是由编译器
定义的。

37. main 主函数执行完毕后,是否可能会再执行一段代码,给出说明?
答案:可以,可以用_onexit 注册一个函数,它会在 main 之后执行 int fn1(void), fn2(void),
fn3(void), fn4 (void);
void main( void )
{
String str("zhanglin");
_onexit( fn1 );
_onexit( fn2 );
_onexit( fn3 );
_onexit( fn4 );
printf( "This is executed first.\n" );
}
int fn1()
{ printf( "next.\n" );
return 0;
}
int fn2()
{
printf( "executed " );
return 0;
}
int fn3()
{
printf( "is " );
return 0;
}
int fn4()
{
printf( "This " );
return 0;
}
The _onexit function is passed the address of a function (func) to be called when the program
terminates normally. Successive calls to _onexit create a register of functions that are executed in
LIFO (last-in-first-out) order. The functions passed to _onexit cannot take parameters.

38. 如何判断一段程序是由C 编译程序还是由C++编译程序编译的?
答案:
#ifdef __cplusplus
cout<<"c++";
#else
cout<<"c";
#endif

39.文件中有一组整数,要求排序后输出到另一个文件中
答案:
#i nclude
#i nclude
using namespace std;

void Order(vector& data) //bubble sort
{
int count = data.size() ;
int tag = false ; // 设置是否需要继续冒泡的标志位
for ( int i = 0 ; i < count ; i++)
{
for ( int j = 0 ; j < count - i - 1 ; j++)
{ if ( data[j] > data[j+1])
{
tag = true ;
int temp = data[j] ;
data[j] = data[j+1] ;
data[j+1] = temp ;
}
}
if ( !tag )
break ;
}
}

void main( void )
{
vectordata;
ifstream in("c:\\data.txt");
if ( !in)
{
cout<<"file error!";
exit(1);
}
int temp;
while (!in.eof())
{
in>>temp;
data.push_back(temp);
}
in.close(); //关闭输入文件流
Order(data);
ofstream out("c:\\result.txt");
if ( !out)
{
cout<<"file error!";
exit(1);
}
for ( i = 0 ; i < data.size() ; i++)
out<out.close(); //关闭输出文件流
}

40. 链表题:一个链表的结点结构
struct Node
{ int data ;
Node *next ;
};
typedef struct Node Node ;

(1)已知链表的头结点 head,写一个函数把这个链表逆序 ( Intel)
Node * ReverseList(Node *head) //链表逆序
{
if ( head == NULL || head->next == NULL )
return head;
Node *p1 = head ;
Node *p2 = p1->next ;
Node *p3 = p2->next ;
p1->next = NULL ;
while ( p3 != NULL )
{
p2->next = p1 ;
p1 = p2 ;
p2 = p3 ;
p3 = p3->next ;
}
p2->next = p1 ;
head = p2 ;
return head ;
}
(2)已知两个链表 head1 和 head2 各自有序,请把它们合并成一个链表依然有序。(保留所有
结点,即便大小相同)
Node * Merge(Node *head1 , Node *head2)
{
if ( head1 == NULL)
return head2 ;
if ( head2 == NULL)
return head1 ;
Node *head = NULL ;
Node *p1 = NULL;
Node *p2 = NULL;
if ( head1->data < head2->data )
{
head = head1 ;
p1 = head1->next;
p2 = head2 ;
}
else
{ head = head2 ;
p2 = head2->next ;
p1 = head1 ;
}
Node *pcurrent = head ;
while ( p1 != NULL && p2 != NULL)
{
if ( p1->data <= p2->data )
{
pcurrent->next = p1 ;
pcurrent = p1 ;
p1 = p1->next ;
}
else
{
pcurrent->next = p2 ;
pcurrent = p2 ;
p2 = p2->next ;
}
}
if ( p1 != NULL )
pcurrent->next = p1 ;
if ( p2 != NULL )
pcurrent->next = p2 ;
return head ;
}
(3)已知两个链表 head1 和 head2 各自有序,请把它们合并成一个链表依然有序,这次要求
用递归方法进行。 (Autodesk)
答案:
Node * MergeRecursive(Node *head1 , Node *head2)
{
if ( head1 == NULL )
return head2 ;
if ( head2 == NULL)
return head1 ;
Node *head = NULL ;
if ( head1->data < head2->data )
{
head = head1 ;
head->next = MergeRecursive(head1->next,head2);
}
else
{
head = head2 ; head->next = MergeRecursive(head1,head2->next);
}
return head ;
}

41. 分析一下这段程序的输出 (Autodesk)
class B
{
public:
B()
{
cout<<"default constructor"<}
~B()
{
cout<<"destructed"<}
B(int i):data(i) //B(int) works as a converter ( int -> instance of B)
{
cout<<"constructed by parameter " << data <}
private:
int data;
};

B Play( B b)
{
return b ;
}
(1) results:
int main(int argc, char* argv[]) constructed by parameter 5
{ destructed B(5)形参析构
B t1 = Play(5); B t2 = Play(t1); destructed t1 形参析构
return 0; destructed t2 注意顺序!
} destructed t1
(2) results:
int main(int argc, char* argv[]) constructed by parameter 5
{ destructed B(5)形参析构
B t1 = Play(5); B t2 = Play(10); constructed by parameter 10
return 0; destructed B(10)形参析构
} destructed t2 注意顺序!
destructed t1

42. 写一个函数找出一个整数数组中,第二大的数 (microsoft) 答案:
const int MINNUMBER = -32767 ;
int find_sec_max( int data[] , int count)
{
int maxnumber = data[0] ;
int sec_max = MINNUMBER ;
for ( int i = 1 ; i < count ; i++)
{
if ( data[i] > maxnumber )
{
sec_max = maxnumber ;
maxnumber = data[i] ;
}
else
{
if ( data[i] > sec_max )
sec_max = data[i] ;
}
}
return sec_max ;
}
43. 写一个在一个字符串(n)中寻找一个子串(m)第一个位置的函数。
KMP 算法效率最好,时间复杂度是O(n+m)。
44. 多重继承的内存分配问题:
比如有 class A : public class B, public class C {}
那么 A的内存结构大致是怎么样的?
这个是 compiler-dependent的, 不同的实现其细节可能不同。
如果不考虑有虚函数、虚继承的话就相当简单;否则的话,相当复杂。
可以参考《深入探索 C++对象模型》,或者:
http://blog.csdn.net/wfwd/archive/2006/05/30/763797.aspx
45. 如何判断一个单链表是有环的?(注意不能用标志位,最多只能用两个额外指针)
struct node { char val; node* next;}
bool check(const node* head) {} //return false : 无环;true: 有环
一种 O(n)的办法就是(搞两个指针,一个每次递增一步,一个每次递增两步,如果有环
的话两者必然重合,反之亦然):
bool check(const node* head)
{
if(head==NULL) return false;
node *low=head, *fast=head->next;
while(fast!=NULL && fast->next!=NULL)
{
low=low->next;
fast=fast->next->next;
if(low==fast) return true; }
return false;
}

46、一个学生的信息是:姓名,学号,性别,年龄等信息,用一个链表,把这些学生信息
连在一起, 给出一个age, 在些链表中删除学生年龄等于age的学生信息。
程序代码
#i nclude "stdio.h"
#i nclude "conio.h"
struct stu{
char name[20];
char sex;
int no;
int age;
struct stu * next;
}*linklist;
struct stu *creatlist(int n)
{
int i;
//h 为头结点,p 为前一结点,s 为当前结点
struct stu *h,*p,*s;
h = (struct stu *)malloc(sizeof(struct stu));
h->next = NULL;
p=h;
for(i=0;i{
s = (struct stu *)malloc(sizeof(struct stu));
p->next = s;
printf("Please input the information of the student: name sex no age n");
scanf("%s %c %d %d",s->name,&s->sex,&s->no,&s->age);
s->next = NULL;
访问固定的内存位置(Accessing fixed memory locations) C C++ Development

47. 嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设
置一绝对地址为 0x67a9 的整型变量的值为 0xaa66。编译器是一个纯粹的ANSI编译器。写
代码去完成这一任务。
这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecast)为一指针
是合法的。这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下:
int *ptr;
ptr = (int *)0x67a9;
*ptr = 0xaa55;
一个较晦涩的方法是:
*(int * const)(0x67a9) = 0xaa55;
即使你的品味更接近第二种方案,但我建议你在面试时使用第一种方案。 中断(Interrupts)
48. 中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准
C支持中断。具代表事实是,产生了一个新的关键字__interrupt。下面的代码就使用了
__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。
__interrupt double compute_area (double radius)
{
double area = PI * radius * radius;
printf(" Area = %f", area);
return area;
}
这个函数有太多的错误了,以至让人不知从何说起了:
1). ISR 不能返回一个值。如果你不懂这个,那么你不会被雇用的。
2). ISR 不能传递参数。如果你没有看到这一点,你被雇用的机会等同第一项。
3). 在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处
的寄存器入栈,有些处理器/编译器就是不允许在 ISR 中做浮点运算。此外,ISR 应该是短
而有效率的,在 ISR 中做浮点运算是不明智的。
4). 与第三点一脉相承,printf()经常有重入和性能上的问题。如果你丢掉了第三和第四点,
我不会太为难你的。不用说,如果你能得到后两点,那么你的被雇用前景越来越光明了。
代码例子(Code examples)

49 . 下面的代码输出是什么,为什么?
void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b > 6) puts("> 6") : puts("<= 6");
}
这个问题测试你是否懂得 C 语言中的整数自动转换原则,我发现有些开发者懂得极少这些
东西。不管如何,这无符号整型问题的答案是输出是“>6”。原因是当表达式中存在有符号
类型和无符号类型时所有的操作数都自动转换为无符号类型。 因此-20 变成了一个非常大
的正整数,所以该表达式计算出的结果大于 6。这一点对于应当频繁用到无符号数据类型的
嵌入式系统来说是丰常重要的。如果你答错了这个问题,你也就到了得不到这份工作的边缘。

50. 评价下面的代码片断:
unsigned int zero = 0;
unsigned int compzero = 0xFFFF;

对于一个 int型不是 16 位的处理器为说,上面的代码是不正确的。应编写如下:
unsigned int compzero = ~0;
这一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的经验里,好的嵌入式程
序员非常准确地明白硬件的细节和它的局限,然而 PC 机程序往往把硬件作为一个无法避免
的烦恼。
到了这个阶段,应试者或者完全垂头丧气了或者信心满满志在必得。如果显然应试者不是很
好,那么这个测试就在这里结束了。但如果显然应试者做得不错,那么我就扔出下面的追加问题,这些问题是比较难的,我想仅仅非常优秀的应试者能做得不错。提出这些问题,我希
望更多看到应试者应付问题的方法,而不是答案。不管如何,你就当是这个娱乐吧…

动态内存分配(Dynamic memory allocation)
51. 尽管不像非嵌入式计算机那么常见,嵌入式系统还是有从堆(heap)中动态分配内存的
过程的。那么嵌入式系统中,动态分配内存可能发生的问题是什么?
这里,我期望应试者能提到内存碎片,碎片收集的问题,变量的持行时间等等。这个主题已
经在 ESP 杂志中被广泛地讨论过了(主要是 P.J. Plauger, 他的解释远远超过我这里能提到
的任何解释),所有回过头看一下这些杂志吧!让应试者进入一种虚假的安全感觉后,我拿
出这么一个小节目:下面的代码片段的输出是什么,为什么?
char *ptr;
if ((ptr = (char *)malloc(0)) == NULL)
puts("Got a null pointer");
else
puts("Got a valid pointer");
这是一个有趣的问题。最近在我的一个同事不经意把 0 值传给了函数 malloc,得到了一个合
法的指针之后,我才想到这个问题。这就是上面的代码,该代码的输出是“Got a valid pointer”。
我用这个来开始讨论这样的一问题,看看被面试者是否想到库例程这样做是正确。得到正确
的答案固然重要,但解决问题的方法和你做决定的基本原理更重要些。

Typedef
52. Typedef 在C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理
器做类似的事。例如,思考一下下面的例子:
#define dPS struct s *
typedef struct s * tPS;
以上两种情况的意图都是要定义dPS 和 tPS 作为一个指向结构s指针。哪种方法更好呢?
(如果有的话)为什么?
这是一个非常微妙的问题,任何人答对这个问题(正当的原因)是应当被恭喜的。答案是:
typedef更好。思考下面的例子:
dPS p1,p2;
tPS p3,p4;
第一个扩展为
struct s * p1, p2;
上面的代码定义 p1 为一个指向结构的指,p2 为一个实际的结构,这也许不是你想要的。第
二个例子正确地定义了 p3 和p4 两个指针。

晦涩的语法
53. C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么?
int a = 5, b = 7, c;
c = a+++b;
这个问题将做为这个测验的一个愉快的结尾。不管你相不相信,上面的例子是完全合乎语法
的。问题是编译器如何处理它?水平不高的编译作者实际上会争论这个问题,根据最处理原
则,编译器应当能处理尽可能所有合法的用法。因此,上面的代码被处理成:
c = a++ + b; 因此, 这段代码持行后 a = 6, b = 7, c = 12。
如果你知道答案,或猜出正确答案,做得好。如果你不知道答案,我也不把这个当作问题。
我发现这个问题的最大好处是:这是一个关于代码编写风格,代码的可读性,代码的可修改
性的好的话题
What will print out?
main()
{
char *p1=“name”;
char *p2;
p2=(char*)malloc(20);
memset (p2, 0, 20);
while(*p2++ = *p1++);
printf(“%sn”,p2);
}
Answer:empty string.
What will be printed as the result of the operation below:
main()
{
int x=20,y=35;
x=y++ + x++;
y= ++y + ++x;
printf(“%d%dn”,x,y);
}
Answer : 5794
What will be printed as the result of the operation below:
main()
{
int x=5;
printf(“%d,%d,%dn”,x,x< <2,x>>2);
}
Answer: 5,20,1
What will be printed as the result of the operation below:
#define swap(a,b) a=a+b;b=a-b;a=a-b;
void main()
{
int x=5, y=10;
swap (x,y);
printf(“%d %dn”,x,y);
swap2(x,y);
printf(“%d %dn”,x,y);
}
int swap2(int a, int b)
{
int temp; temp=a;
b=a;
a=temp;
return 0;
}
Answer: 10, 5
10, 5
What will be printed as the result of the operation below:
main()
{
char *ptr = ” Cisco Systems”;
*ptr++; printf(“%sn”,ptr);
ptr++;
printf(“%sn”,ptr);
}
Answer:Cisco Systems
isco systems
What will be printed as the result of the operation below:
main()
{
char s1[]=“Cisco”;
char s2[]= “systems”;
printf(“%s”,s1);
}
Answer: Cisco
What will be printed as the result of the operation below:
main()
{
char *p1;
char *p2;
p1=(char *)malloc(25);
p2=(char *)malloc(25);
strcpy(p1,”Cisco”);
strcpy(p2,“systems”);
strcat(p1,p2);
printf(“%s”,p1);
}
Answer: Ciscosystems
The following variable is available in file1.c, who can access it?:
static int average;
Answer: all the functions in the file1.c can access the variable.
WHat will be the result of the following code?
#define TRUE 0 // some code
while(TRUE) {
// some code
}
Answer: This will not go into the loop as TRUE is defined as 0.
What will be printed as the result of the operation below:
int x;
int modifyvalue()
{
return(x+=10);
}
int changevalue(int x)
{
return(x+=1);
}
void main()
{
int x=10;
x++;
changevalue(x);
x++;
modifyvalue();
printf("First output:%dn",x);
x++;
changevalue(x);
printf("Second output:%dn",x);
modifyvalue();
printf("Third output:%dn",x);
}
Answer: 12 , 13 , 13
What will be printed as the result of the operation below:
main()
{
int x=10, y=15;
x = x++;
y = ++y;
printf(“%d %dn”,x,y);
}
Answer: 11, 16
What will be printed as the result of the operation below:
main()
{
int a=0;
if(a==0)
printf(“Cisco Systemsn”); printf(“Cisco Systemsn”);
}
Answer: Two lines with “Cisco Systems” will be printed.


/*****************************************************************************/
1. 多态类中的虚函数表是 Compile-Time,还是 Run-Time 时建立的?

2.将一个 1M -10M 的文件,逆序存储到另一个文件,就是前一个文件的最后一个
字符存到新文件的第一个字符,以此类推。

3.main 主函数执行完毕后,是否可能会再执行一段代码?

4.一个父类写了一个 virtual 函数,如果子类覆盖它的函数不加 virtual ,也能实现多态?
在子类的空间里,有没有父类的这个函数,或者父类的私有变量?

5.给一个字符串、例如 “ababc”要求返回“ab”. 因为“ab”连续重复出现且最长。
用C/C++语言写一函数完成该算法,给出复杂度

6.对序列1、1、2、3、5、8、13。。。。 是 Fab..数列
2、3、5、13...是 Fab..质数数列,因为他们与自己前面的 Fab...数列都互质
给出 k,返回第 k 小的 Fab..质数

7.101 个硬币 100 真、1 假,真假区别在于重量。请用无砝码天平称两次给出真币重还是假
币重的结论。

8.完成字符串拷贝可以使用 sprintf、strcpy 及 memcpy 函数,请问这些函数有什么区别,
你喜欢使用哪个,为什么?

9.变量的声明和定义有什么区别?

10.请写出下面代码在 32 位平台上的运行结果,并说明 sizeof 的性质:
#include
#include

int main(void)
{
char a[30];
char *b = (char *)malloc(20 * sizeof(char));
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(b));
printf("%d\n", sizeof(a[3]));
printf("%d\n", sizeof(b+3));
printf("%d\n", sizeof(*(b+4))); return 0 ;
}

12.请完成以下题目。注意,请勿直接调用 ANSI C 函数库中的函数实现。
a)请编写一个 C 函数,该函数给出一个字节中被置 1 的位的个数,并请
给出该题的至少一个不同解法。
b)请编写一个 C 函数,该函数将给定的一个字符串转换成整数。
c)请编写一个 C 函数,该函数将给定的一个整数转换成字符串。
d)请编写一个 C 函数,该函数将一个字符串逆序。
e)请编写一个 C 函数,该函数在给定的内存区域搜索给定的字符,并返回
该字符所在位置索引值。
f)请编写一个 C 函数,该函数在一个字符串中找到可能的最长的子字符串,
该字符串是由同一字符组成的。

给出演示上述函数功能的一个简单程序,并请编写对应的 Makefile 文件

13.我们需要编写一个图形相关的应用程序,需要处理大量图形(Shape)信息,
图形有矩形(Rectangle),正方形(Square),圆形 (Circle)等种类,应用
需要计算这些图形的面积,并且可能需要在某个设备上进行显示(使用在标准
输出上打印信息的方式做为示意)。
a)请用面向对象的方法对以上应用进行设计,编写可能需要的类
b)请给出实现以上应用功能的示例性代码,从某处获取图形信息,
并且进行计算和绘制
c)如果你的 Square 继承自 Rectangle,请给出理由,如果不是,
请给出理由,并且请比较两种方式的优劣
d)请问你所编写的类,在如下代码中会有何表现,请解释
void test_rectangle_area(Rectangle& r)
{
r.set_width(10);
r.set_height(15);
assert(r.area() == 150);
}

14.假设现有一个单向的链表,但是只知道只有一个指向该节点的指针 p,并且假设这个节点
不是尾节点,试编程实现删除此节点。

15.写一个程序,把一个 100 以内的自然数分解因数。(自然数分解因数就是将一个自然数分
解为几个素数的乘积,提示,由于该数不是很大,所以可以将质数保存在数组中,以加快计算速
度)

16.编写一个 Identify的分配、释放的函数,为 1-10000 之间的自然数。

17.分别实现 itoa和 atoi.
18.Consider the following code:

#include
#include
int main(int argc, char *argv[]) {
int i = 1;
char buf[4];
strcpy(buf, "AAAA");
printf("%d\n", i);
return 0;
}

a) When compiled and executed on x86, why does this program usually not
output what the programmer intended?

b) Name several ways in which the security problem that causes this
program not to output what the programmer intended can be prevented
WITHOUT changing the code.

19. 说出结果
int w=1,x=2,y=3,z=4;
m=(wm=(mm=(m<2)?m:z;
printf("m=%d",m);

20.说出结果
#include
main()
{
FILE *fp;
int i,a[4]={1,2,3,4},b;
fp=fopen("data.dat","wb");//这里帮忙解释一下
for(i=0;i<4;i++)
fwrite(&a[i],sizeof(int),1,fp);//这里也帮忙看一下
fclose(fp);
fp=fopen("data.dat","rb");
fseek(fp,-2L*sizeof(int),SEEK_END);//还有这里
fread(&b,sizeof(int),1,fp);//这里还有也看一下
fclose(fp);
printf("b=%d\n",b);
}

21.有双向循环链表结点: typedef struct node
{
int date;
struct node *front,*next;
}_Node;
有两个双向循环链表 A,B,知道其头指针为:pHeadA,pHeadB,请写一函数将两上链表中
date 值相同的结点删除

22.
char * GetStr()
{
char *tmp;
tmp = "123"
return tmp;
}

void main()
{
printf("%s", GetStr());
}

会输出 123吗?123 创建在堆上还是栈上呢?123的空间是什么时候释放的?

23.字符指针、浮点数指针、以及函数指针这三种类型的变量哪个占用的内存最大?为什么?
类ClassB从ClassA派生,那么ClassA *a = new ClassB(…); 试问该表达是否合法?为什么?
如果 ClassA 中定义并实现虚函数 int func(void),ClassB 中也实现该函数,那么上述变量
a->func()将调用哪个类里面的函数?如果 int func(void)不是虚函数,情况又如何?为什么?
char **p, a[16][8]; 问:p=a 是否会导致程序在以后出现问题?为什么?
如下所述的 if else 和 switch 语句哪个的效率高?为什么?
在同一个进程中,一个模块是否可以通过指针操作破坏其它模块的内存,为什么?
应用程序在运行时的内存包括代码区和数据区,其中数据区又包括哪些部分?

24.Assignment 2: Picture Processing

Use C++, Java, or similar languages or/and any middleware such as EJB and J2EE to process a
picture with a high resolution (3 Mega Pixels for example). Use some methodologies to degrade
the resolution of the picture to make it quicker for browsing. Then divide the degraded picture
into 9 sectors equally. Click any of the 9 sectors will result a detailed picture for this sector with
the same resolution as that of the original picture. This assignment is designed for you to
demonstrate your ability to handle pictures.

25.用<<, >>, |, &实现一个WORD(2 个字节)的高低位交换!!

26.要开辟 P1,P2,P3,P4 内存来做缓冲,大小自定,但这四个缓冲的大小要一样,并且是连续的!
27.有一浮点型数组 A,用 C 语言写一函数实现对浮点数组 A 进行降序排序,并输出结果,要求
要以数组 A作为函数的入口.(建议用冒泡排序法)

28.找错:
#include
#include
class Base
{
private:
char * name;
public:
Base(char * className)
{
name = new char[strlen(className)];
strcpy(name, className);
}
~Base()
{
delete name;
}
char * copyName()
{
char newname [256];
strcpy(newname, name);
return newname;
}
char * getName()
{
return name;
}
static void print(Base base)
{
printf("name: %s\n" , base.name);
}
};
class Subclass : public Base
{
public:
Subclass(char * className) : Base(className)
{
}
};
int main() {
Base * pBase = new Subclass("test");
Base::print(*pBase);
printf("name: %s\n", pBase->getName());
printf("new name: %s\n", pBase->copyName());
return 0;
}

29.编写一个函数,函数接收一个字符串,是由十六进制数组成的一组字符串,函数的功能是把
接到的这组字符串转换成十进制数字.并将十进制数字返回.

30.编写一个函数将一条字符串分成两部分,将前半部分按 ASCII 码升序排序,后半部分不
变,(如果字符串是奇数则中间的字符不变,)最后再将前后两部分交换,然后将该字符串输
出,测试字符串“ADZDDJKJFIEJHGI”

31.找错
Void test1()
{
char string[10];
char* str1="0123456789";
strcpy(string, str1);
}

Void test2()
{
char string[10], str1[10];
for(I=0; I<10;I++)
{
str1[i] ='a';
}
strcpy(string, str1);
}

Void test3(char* str1)
{
char string[10];
if(strlen(str1)<=10)
{
strcpy(string, str1);
}
}

32. 找错
#define MAX_SRM 256
DSN get_SRM_no()
{
static int SRM_no;
int I;
for(I=0;I{
SRM_no %= MAX_SRM;
if(MY_SRM.state==IDLE)
{
break;
}
}
if(I>=MAX_SRM)
return (NULL_SRM);
else
return SRM_no;
}

33. 写出程序运行结果

int sum(int a)
{
auto int c=0;
static int b=3;
c+=1;
b+=2;
return(a+b+C);
}

void main()
{
int I;
int a=2;
for(I=0;I<5;I++)
{
printf("%d,", sum(a));
}
}

34.
int func(int a)
{
int b;
switch(a) {
case 1: 30;
case 2: 20;
case 3: 16;
default: 0
}
return b;
}
则 func(1)=?

35:
int a[3];
a[0]=0; a[1]=1; a[2]=2;
int *p, *q;
p=a;
q=&a[2];
则 a[q-p]=?

36. 定义 int **a[3][4], 则变量占有的内存空间为:_____

37.编写一个函数,要求输入年月日时分秒,输出该年月日时分秒的下一秒。如输入 2004 年
12月 31 日23 时59分 59秒,则输出 2005 年1 月1日 0 时0 分0 秒。

38.写一个函数,判断一个 int 型的整数是否是 2的幂,即是否可以表示成 2^X的形式(不可
以用循环)
我只知道是用递推,大概写了一下,如下:
int IsTwoPow(int s)
{
if(s==1)return FALSE;
s=s>>1;
if(s>1)IsTwoPow(s);
return (s==1)?TRUE:FALSE;//大概是这个意思,但是这一句似乎不该这么返回!
}

39 A,B 从一堆玻璃球(共 100 个)里向外拿球,规则如下:
(1)A先拿,然后一人一次交替着拿;
(2)每次只能拿 1 个或2 个或4 个;
(3)谁拿最后一个球,谁就是最后的失败者;
问 A,B谁将是失败者?写出你的判断步骤。

40.已知:无序数组,折半查找,各元素值唯一。
函数原型是:Binary_Seach(int array[], int iValue, int iCount)
array 是数组,在里面用折半查找的方法找等于 iValue 的值,找到返回 1 否则 0,iCount 是
元素个数
41.统计一个字符串中字符出现的次数

42.100 位以上的超大整数的加法(主要考虑数据结构和加法的实现)。

43.对如下电文:"CASTCASTSATATATASA"给出 Huffman 编码。

44.int (* (*f)(int, int))(int)表示什么含义?

45.x=x+1,x+=1,x++,为这三个语句的效率排序。并说明为什么。

46.中缀表达式 A-(B+C/D)*E 的后缀形式是什么?

47.struct S1
{
char c;
int i;
};
sizeof(S1) = ?

class X{
public:
X();
virtual ~X();
void myMemberFunc();
static void myStaticFunc();
virtual void myVirtualFunc();
private:
int i;
char * pstr;
char a;
}
sizeof(X) = ?

48.找出两个字符串中最大子字符串,如"abractyeyt","dgdsaeactyey"的最大子串为"actyet"

49.有一百个整数,其中有负数,找出连续三个数之和最大的部分.

50.写一程序实现快速排序. 假设数据输入为一文件
快速算法描述如下
Algorithm Partition
Input: sequence a0, ..., an-1 with n elements
Output: permutation of the sequence such that all elements a0, ..., aj are less than or equal to all
elements ai, ..., an-1 (i > j) Method:

choose the element in the middle of the sequence as comparison element x
let i = 0 and j = n-1
while ij

search the first element ai which is greater than or equal to x
search the last element aj which is less than or equal to x
if ij

exchange ai and aj
let i = i+1 and j = j-1
After partitioning the sequence, Quicksort treats the two parts recursively by the same procedure.
The recursion ends whenever a part consists of one element only.

51.写一算法检测单向链表中是否存在环(whether there is a loop in a link list),
要求算法复杂度(Algorithm's complexity 是 O(n)) 并只使用常数空间(space is O(c)).
注意,你只知道一个指向单向链表头的指针。链表的长度是不定的,而且环出现的地方也是
不定的,环有可能在头,有可能在中间。而且要求是检测, 不能破坏环的结构.

52.设下列函数已经通过了调试
bool Sort_Array(ArrayType * Pinputarray, ArrayType * Poutarray);
该函数在内存中排序,能把字节数最大为 100M 字节的 ArrayType 类型的数组排序。其中
ArrayType 是一个
预定义的数组类型(细节无关紧要),Pinputarray,Poutarray 分别为排序前的指针和排序后
的指针。
请用 c 语言的伪码风格设计一个算法,他调用上面给出的函数完成下列从输入到输出的任
务:
输入:排序前的大文件,名称为 char * pinoutfilename ,其内容为用分号分隔的 ArrayType
类型的数组元素,可装满 4 个100M 字节的数组。
输出:排序后的大文件 char * poutoutfilename。

53.用最有效率的方法算出 2 乘以8等於几?
54.
1.错误的转义字符是 (c )
A.'\091'
B.'\\'
C.'\0' D.'\''

2.若数组名作实参而指针变量作形参,函数调用实参传给形参的是 (d )
A.数组的长度 B.数组第一个元素的值
C.数组所有元素的值 D.数组第一个元素的地址

3.变量的指针含意是指变量的 (b ) A.值 B.地址
C.存储 D.名字

5.某文件中定义的静态全局变量(或称静态外部变量)其作用域是 (d )
A.只限某个函数 B.本文件
C.跨文件 D.不限制作用域
55.
1. 解二次方程:a*x*x+b*x+c
int Quadratic( double a,double b,double c,double& x1,double& x2);
返回值:解的个数

2. 最大公约数
DWORD Divisor( DWORD dwFirst, DWORD dwSecond );
返回值:最大公约数

3. 根据蒙特卡洛算法计算圆周率
double PI( DOWRD dwCount/*测试次数*/ );
返回值:PI

4. 无符号整数乘法,乘数为 32bit,结果为 64bit
提示:32bit整数分解为 16bit 相乘
void Multiply( DWORD dwFirst, DWORD dwSecond, DWORD& dwHigh, DWORD&
dwLower );


5. 链表排序(从小到大)
节点定义为:
struct Node{
int nValue;
struct Node* pNext;
};
最后一个节点的 pNext = NULL.
Node* SortChain( Node* pHead );
返回值:链表头

转载于:https://www.cnblogs.com/FKChengDuRen/p/3617214.html

你可能感兴趣的:(华为C++笔试题及答案)