1.A是B和C的父类;
2.B有元素int a,b.B有元素float a,b;
3.要求A不能生成对象,B和C可以生成对象。而且对象可以互相相加
(a与a相加,b与b相加)和夫植(a=a,b=b),
4.ABC有print函数,用printf打印出类名,a-b的植。
5. 函数main中含有以下部分
void main (int argc,char*argv[])
{
B b (1,2);
C c (1.1,1.2),c2;
c2=b+c,
vector<A*> v;
v.push_back((A*)&b);
v.push_back((A*)&c);
v.push_back((A*)&c2);
vector<A*>::iterator it = v.begin();
for (;it!=v.end();it++)
{
((A*)(*it)->pritt();
}
}
1 #include “filename.h”和#include <filename.h>的区别?
对于#include <filename.h> ,编译器从标准库路径开始搜索 filename.h
对于#include “filename.h” ,编译器从用户的工作路径开始搜索 filename.h
2 const的作用是什么?
答:(1)可以定义 const 常量
(2)const可以修饰函数的参数、返回值,甚至函数的定义体。被const
修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。
3 C++函数中值的传递方式有哪几种?
答:C++函数的三种传递方式为:值传递、指针传递和引用传递。
4 内存的分配方式的分配方式有几种?
答:一、从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量。
二、在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
三、从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。
生命期
1.静态分配的区域的生命期是整个软件运行期,就是说从软件运行开始到软件终止退出。只有软件终止运行后,这块内存才会被系统回收
2.在栈中分配的空间的生命期与这个变量所在的函数和类相关。如果是函数中定义的局部变量,那么它的生命期就是函数被调用时,如果函数运行结束,那么这块内存就会被回收。如果是类中的成员变量,则它的生命期与类实例的生命期相同
3.在堆上分配的内存,生命期是从调用new或者malloc开始,到调用delete或者free结束。如果不用delete或者free。则这块空间必须到软件运行结束后才能被系统回收。
常见的内存错误及其对策
1 内存分配未成功,却使用了它。
编程新手常犯这种错误,因为他们没有意识到内存分配会不成功。常用解决办法是,在使用内存之前检查指针是否为NULL。如果指针p是函数的参数,那么在函数的入口处用assert(p!=NULL)进行检查。如果是用malloc或new来申请内存,应该用if(p==NULL) 或if(p!=NULL)进行防错处理。
2 内存分配虽然成功,但是尚未初始化就引用它。
犯这种错误主要有两个起因:一是没有初始化的观念;二是误以为内存的缺省初值全为零,导致引用初值错误(例如数组)。内存的缺省初值究竟是什么并没有统一的标准,尽管有些时候为零值,我们宁可信其无不可信其有。所以无论用何种方式创建数组,都别忘了赋初值,即便是赋零值也不可省略,不要嫌麻烦。
3 内存分配成功并且已经初始化,但操作越过了内存的边界。
例如在使用数组时经常发生下标“多1”或者“少1”的操作。特别是在for循环语句中,循环次数很容易搞错,导致数组操作越界。
4 忘记了释放内存,造成内存泄露。
含有这种错误的函数每被调用一次就丢失一块内存。刚开始时系统的内存充足,你看不到错误。终有一次程序突然死掉,系统出现提示:内存耗尽。
动态内存的申请与释放必须配对,程序中malloc与free的使用次数一定要相同,否则肯定有错误(new/delete同理)。
5 释放了内存却继续使用它。
有三种情况:
(1)程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存,此时应该重新设计数据结构,从根本上解决对象管理的混乱局面。
(2)函数的return语句写错了,注意不要返回指向“栈内存”的“指针”或者“引用”,因为该内存在函数体结束时被自动销毁。
(3)使用free或delete释放了内存后,没有将指针设置为NULL。导致产生“野指针”。
综上所述,我们应该注意:
1.用malloc或new申请内存之后,应该立即检查指针值是否为NULL。防止使用指针值为NULL的内存。
2.不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。
3.避免数组或指针的下标越界,特别要当心发生“多1”或者“少1”操作。
4.动态内存的申请与释放必须配对,防止内存泄漏。
5.用free或delete释放了内存之后,立即将指针设置为NULL,防止产生“野指针”。
下面举几个经典的错误例子,大家不要犯同样的错误:
1. 返回栈内存指针
char *GetString(void)
{
char *p = "hello world";
return p;
}
char* pGet = GetString();
这段程序编译时没有错误,运行也没有错误,但是你却无法使得返回的pGet指针指向的数据是你想要的“hello world”,因为指针p的生命期是函数GetString内,运行完函数GetString后,p分配的栈空间马上被系统回收了。虽然pGet指向了p当初分配的内存地址,但是那块地址已经没有内容了。
2.这是一个出现频率非常高的错误
char* pChar = new char;
……
int a ;
pChar = &a;
……
delete pChar;
当然这是一个例子,具体的程序各有不同。这段程序有两个问题。
1).是pChar = &a;将导致pChar原先分配的空间无法再被获取,就象我们的丢失了朋友的电话号码一样,无法再联系这个朋友了。这就造成了内存泄漏。如果内存泄漏多了,可能导致系统的崩溃,因为可用的资源将越来越少,直到枯竭为止。
2)是delete pChar将导致异常发生,因为这时的pChar已经不是指向动态分配的内存了,而是指向了a分配的栈空间,而栈空间是不能使用delete来回收的,因此将导致内存异常。
5 实现双向链表删除一个节点P,在节点P后插入一个节点,写出这两个函数;
//在带头结点的双链表中,将值为x的新结点插入*p之前,设p≠NULL
void DInsertBefore(DListNode *p,DataType x)
{
DListNode *s=malloc(sizeof(DListNode));//①
s->data=x;//②
s->prior=p->prior;//③
s->next=p;//④
p->prior->next=s;//⑤
p->prior=s;//⑥
}
//在带头结点的双链表中,删除结点*p,设*p为非终端结点
void DDeleteNode(DListNode *p)
{
p->prior->next=p->next;//①
p->next->prior=p->prior;//②
free(p);//③
}
6 写一个函数,将其中的\t都转换成4个空格。
char* convert(char *strDest, const char *strSrc)
{
char * cp=strDest;
while((void*)strSrc!=NULL &&(void*)strDest!=NULL&& *strSrc!='\0') // 跳出条件
{ //cout<<"0x"<<setfill('0')<<setw(8)<<setiosflags(ios::uppercase)<<hex<<(int)p<<dec<<setfill(' ')<<endl;
if (*strSrc=='\t') //将\t转换成4个空格
{
for(int j=0;j<4;j++)
{
*strDest=' ';
strDest++;
}
}
else //否则直接拷贝
{
(*strDest)=(*strSrc);
strDest++;
}
strSrc++;
}
return strDest;
}
指针对于字符的处理却有些特殊,和前面的非字符的指针输出处理要分开理解。
比如,我们定义一个 char a='A'; char *p=&a; 如果我们调用上面非字符指针的输出方式,结果如下:
方式1 cout<<p<<endl; 结果 A####(#表示乱码,不可识别) 并不是地址
方式2 cout<<*p<<endl; 结果 A 这和非字符的指针情况一样,输出指针指向的内容
而且我们直接操作 cout<<&a<<endl; 结果和方式1的结果是完全相同的
为什么方式1输出的不是地址呢?这里有一个特殊的处理,虽然这里的p的内容确确实实是一个地址,但是cout操作字符指针的话,它遇到地址,就会直接去寻找这个地址所指向的内容,并把它的空间里的机器数按照字符的规则转化成字符输出,直到遇到“\0”这个操作符才停止。所以我们直接输出p的时候,它先输出‘A’然后再继续读取后面的内存空间知道遇到“\0”,显示结果是“A+乱码”。
你肯定会说,为什么要这样呢,这样多不方便呀,其实这么做是有目的的,而且恰恰就是为了方便才这么设置的。因为这样就可以很容易的处理字符串了,而处理字符串是我们在计算机中用得很多的操作。
比如我们第一个字符串数组 char a[]="mantou"; a[]在内存中在7个字节,而不是6个,因为在mantou字符串后面还隐藏有一个“\0”,这时我们用 char *p=a; (这里不用&a是因为,a[]是一个数组,数组名a本身就是一个指针常量) 输出操作 cout<<p<<endl; 这里就不会输出地址,而是直接输出整个mantou字符串,很方便哈,如果我们 cout<<*p<<endl; 结果显示的是m,因为p是指向数组的首元素的地址的,就是指向这里的储存m的空间的地址,所以取p的内容(*p),只能输出一个m哦。
虽然通常情况下我们是不需要了解我们的数据地址的,但我也顺便说说,怎么得到字符指针的地址,也可以方便大家对内存地址的分配再做更深入的研究。
char a='A'; 如果这里直接输出 cout<<&a<<endl; 当然是不能输出地址的,原理上面已经说过了,cout遇到字符型地址就会转换成字符输出。我们可以用指针p先取得a的地址(char *p=&a;),但是这样用 cout<<p<<endl; 也并不能得到地址呀,做个小技巧,首先我们知道p中的内容本身就是地址,但是因为它是字符串,我们又不能直接输出它,所以呀,我们可以把指针里的内容(记载的是一个地址数据)强制转化成整型再输出 cout<<(int)p<<endl; 呵呵,这样就得到了这个指针里的内容——十进制型的地址,而我们知道,地址是用十六进制表示的,形式是 0x######## 0x后面加8位十六进制数,我们把我们先得到的十进制地址按照地址的表示形式用流操作转化成十六进制就可以了。代码如下:
cout<<"0x"<<setfill('0')<<setw(8)<<setiosflags(ios::uppercase)<<hex<<(int)p<<dec<<setfill(' ')<<endl; //流控制实现十六进制地址输出
注意不要忘了 #include<iomanip.h> 这个头文件哦
对了,还忘了说一点,你可能会发现,用cout<<&p<<endl;也可以输出地址,但是要注意的是任何变量都是占有储存空间的,指针也是,所以这个输出的地址不是指针里的内容,即不是指针所指向空间的地址,而是指针变量空间本身的地址。# cout << (void*)p就行了iso标准规定了stl的行为,对能隐式转化到const char*的指针cout << *中的operator <<都调用 basic_ostream& operator<<(basic_ostream&, const char*); 而其他cout << *形式中能隐式转换到const void*的指针都调用 basic_ostream& basic_ostream::operator<<(const void*);
7 Windows程序的入口是哪里?写出Windows消息机制的流程.
8 如何定义和实现一个类的成员函数为回调函数?
9 C++里面是不是所有的动作都是main()引起的?如果不是,请举例.
10 C++里面如何声明const void f(void)函数为C程序中的库函数?
11 下列哪两个是等同的
int b;
A const int* a = &b; //指向常量的指针 ,不能通过指针改变b,但指针的地址可以改变。
B const* int a = &b;// 指针的地址不可以改变,但可以通过指针改变b的值
C const int* const a = &b; //指针指向的值,和指针本身的地址都不能改变
D int const* const a = &b;//与c相同
12 内联函数在编译时是否做参数类型检查
内联函数不是在调用时发生控制转移,而是在编译时将函数体嵌入在每一个调用语句处。Inline 类型说明符 被调用的函数名 (含类型说明的形参表)
13 三个float:a,b,c
问值
(a+b)+c==(b+a)+c
(a+b)+c==(a+c)+b
14 把一个链表反向填空
15 设计一个重采样系统,说明如何anti-alias
16 某个程序在一个嵌入式系统(200M的CPU,50M的SDRAM)中已经最优化了,换到另一个系统(300M的CPU,50M的SDRAM)中运行,还需要优化吗?
17. 下面哪种排序法对12354最快
a quick sort
b.buble sort
c.merge sort
18. 哪种结构,平均来讲,获取一个值最快
a. binary tree
b. hash table
c. stack
19 请问C++的类和C里面的struct有什么区别?
20 请讲一讲析构函数和虚函数的用法和作用?
21 全局变量和局部变量有什么区别?实怎么实现的?操作系统和编译器是怎么知道的?
22 一些寄存器的题目,主要是寻址和内存管理等一些知识。
23 8086是多少尉的系统?在数据总线上是怎么实现的?
24 多态。overload 和 override的区别。
<<Sony笔试题>>
25.完成下列程序
*
*.*.
*..*..*..
*...*...*...*...
*....*....*....*....*....
*.....*.....*.....*.....*.....*.....
*......*......*......*......*......*......*......
*.......*.......*.......*.......*.......*.......*.......*.......
#include <stdio.h>
#define N 8
int main()
{
int i;
int j;
int k;
---------------------------------------------------------
for (i=N;i>=1;i--)
{
for (j=0;j<N-i+1;j++)
{
cout<<"*";
for (k=1;k<N-i+1;k++)
{
cout<<".";
}
}
cout<<endl;
}
---------------------------------------------------------
return 0;
}
26 完成程序,实现对数组的降序排序
#include <stdio.h>
void sort(int array[] );
int main()
{
int array[]={45,56,76,234,1,34,23,2,3}; //数字任//意给出
sort( array );
return 0;
}
void sort( int array[] )
{
____________________________________
int i,j,k;
for(i=1;i<=7;i++)
{
if(array[i]>array[i-1])
{
k=ARRAY[i];
j=i-1;
do
{
array[j+1]=array[j];
j-- ;
}
while(k>array[j]&&j>=0);
array[j+1]=k;
}
}
-----------------------------------------------------
}
27 费波那其数列,1,1,2,3,5, 8……编写程序求第十项。可以用递归,也可以用其他方法,但要说明你选择的理由。
#include <stdio.h>
int Pheponatch(int);
int main()
{
printf("The 10th is %d",Pheponatch(10));
return 0;
}
int Pheponatch(int N)
int m;
vector <int> array;
array.push_back(1);
array.push_back(1);
for (int i=2;i<=N;i++)
{
m=array[i-2];
array.push_back(m+array[i-1]);
}
return array[N];
--------------------------------
}
28 下列程序运行时会崩溃,请找出错误并改正,并且说明原因。
#include <stdio.h>
#include <malloc.h>
typedef struct{
TNode* left;
TNode* right;
int value;
} TNode;
TNode* root=NULL;
void append(int N);
int main()
{
append(63);
append(45);
append(32);
append(77);
append(96);
append(21);
append(17); // Again, 数字任意给出
}
void append(int N)
{
TNode* NewNode=(TNode *)malloc(sizeof(TNode));
NewNode->value=N;
if(root==NULL)
{
root=NewNode;
return;
}
else
{
TNode* temp;
temp=root;
while((N>=temp.value && temp.left!=NULL) ||
(N<temp. value && temp. right!=NULL))
{
while(N>=temp.value && temp.left!=NULL)
temp=temp.left;
while(N<temp.value && temp.right!=NULL)
temp=temp.right;
}
if(N>=temp.value)
temp.left=NewNode;
else
temp.right=NewNode;
return;
}
}
29. A class B network on the internet has a subnet mask of 255.255.240.0, what is the maximum number of hosts per subnet .
a. 240 b. 255 c. 4094 d. 65534
30. What is the difference: between o(log n) and o(log n^2), where both logarithems have base 2 .
a. o(log n^2) is bigger b. o(log n) is bigger
c. no difference
31. For a class what would happen if we call a class’s constructor from with the same class’s constructor .
a. compilation error b. linking error
c. stack overflow d. none of the above
32. “new” in c++ is a: .
a. library function like malloc in c
b. key word c. operator
d. none of the above
33. Which of the following information is not contained in an inode .
a. file owner b. file size
c. file name d. disk address
34. What’s the number of comparisons in the worst case to merge two sorted lists containing n elements each .
a. 2n b.2n-1 c.2n+1 d.2n-2
35. Time complexity of n algorithm T(n), where n is the input size ,is T(n)=T(n-1)+1/n if n>1 otherwise 1 the order of this algorithm is .
a. log (n) b. n c. n^2 d. n^n
36. The number of 1’s in the binary representation of 3*4096+ 15*256+5*16+3 are .
a. 8 b. 9 c. 10 d. 12
37.设计函数 int atoi(char *s)。
38.int i=(j=4,k=8,l=16,m=32); printf(“%d”, i); 输出是多少?
答:相当于 i=j=4;
i=k=8;
i=l=16;
i=m=32; 故 最后i=32;
39.解释局部变量、全局变量和静态变量的含义。
40.解释堆和栈的区别。
41.论述含参数的宏与函数的优缺点。
42. 以下三条输出语句分别输出什么?[C易]
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; // false
cout << boolalpha << ( str3==str4 ) << endl; //false 数组不可能等
cout << boolalpha << ( str5==str6 ) << endl; // true
str1和str2都是字符数组,每个都有其自己的存储区,它们的值则是各存储区首地址,不等;str3和str4同上,只是按const语义,它们所指向的数据区不能修改。str5和str6并非数组而是字符指针,并不分配存储区,其后的“abc”以常量形式存于静态数据区,而它们自己仅是指向该区首地址的指针,相等。
43. 非C++内建型别 A 和 B,在哪几种情况下B能隐式转化为A?[C++中等]
答:
a. class B : public A { ……} // B公有继承自A,可以是间接继承的
b. class B { operator A( ); } // B实现了隐式转化为A的转化
c. class A { A( const B& ); } // A实现了non-explicit的参数为B(可以有其他带默认值的参数)构造函数
d. A& operator= ( const A& ); // 赋值操作,虽不是正宗的隐式类型转换,但也可以勉强算一个
44. 以下代码中的两个sizeof用法有问题吗?[C易]
void UpperCase( char str[] ) // 将 str 中的小写字母转换成大写字母
{
for( size_t i=0; i<sizeof(str)/sizeof(str[0]); ++i )
if( 'a'<=str[i] && str[i]<='z' )
str[i] -= ('a'-'A' );
}
char str[] = "aBcDe";
cout << "str字符长度为: " << sizeof(str)/sizeof(str[0]) << endl;
UpperCase( str );
cout << str << endl;
答:函数内的sizeof有问题。根据语法,sizeof如用于数组,只能测出静态数组的大小,无法检测动态分配的或外部数组大小。函数外的str是一个静态定义的数组,因此其大小为6,函数内的str实际只是一个指向字符串的指针,没有任何额外的与数组相关的信息,因此sizeof作用于上只将其当指针看,一个指针为4个字节,因此返回4。
45. 以下代码有什么问题?[C难]
void char2Hex( char c ) // 将字符以16进制表示
{
char ch = c/0x10 + '0';
if( ch > '9' )
{
ch += ('A'-'9'-1);
char cl = c%0x10 + '0';
}
if( cl > '9' )
{
cl += ('A'-'9'-1);
cout << ch << cl << ' ';
}
}
char str[] = "I love 中国";
for( size_t i=0; i<strlen(str); ++i )
char2Hex( str[i] );
cout << endl;
46. 以下代码有什么问题?[C++易]
struct Test
{
Test( int ) {}
Test() {}
void fun() {}
};
void main( void )
{
Test a(1);
a.fun();
Test b();
b.fun();
}
答:变量b定义出错。按默认构造函数定义对象,不需要加括号。
47. 以下代码有什么问题?[C++易]
cout << (true?1:"1") << endl;
答:三元表达式“?:”问号后面的两个操作数必须为同一类型。
8. (1)以下代码能够编译通过吗,为什么?[C++易]
unsigned int const size1 = 2;
char str1[ size1 ];
unsigned int temp = 0;
cin >> temp;
unsigned int const size2 = temp;
char str2[ size2 ];
答:str2定义出错,size2非编译器期间常量,而数组定义要求长度必须为编译期常量。
(2)以下反向遍历array数组的方法有什么错误?[STL易]
vector array;
array.push_back( 1 );
array.push_back( 2 );
array.push_back( 3 );
for( vector::size_type i=array.size()-1; i>=0; --i ) // 反向遍历array数组
{
cout << array[i] << endl;
}
答:首先数组定义有误,应加上类型参数:vector<int> array。其次vector::size_type被定义为unsigned int,即无符号数,这样做为循环变量的i为0时再减1就会变成最大的整数,导致循环失去控制
48. 以下代码中的输出语句输出0吗,为什么?[C++易]
struct CLS
{
int m_i;
CLS( int i ) : m_i(i)
{
}
CLS()
{
CLS(0);
}
};
CLS obj;
cout << obj.m_i << endl;
答:不能。在默认构造函数内部再调用带参的构造函数属用户行为而非编译器行为,亦即仅执行函数调用,而不会执行其后的初始化表达式。只有在生成对象时,初始化表达式才会随相应的构造函数一起调用。
49. C++中的空类,默认产生哪些类成员函数?[C++易]
答:
class Empty
{
public:
Empty(); // 缺省构造函数
Empty( const Empty& ); // 拷贝构造函数
~Empty(); // 析构函数
Empty& operator=( const Empty& ); // 赋值运算符
Empty* operator&(); // 取址运算符
const Empty* operator&() const; // 取址运算符 const
};
50. 以下两条输出语句分别输出什么?[C++难]
float a = 1.0f;
cout << (int)a << endl;
cout << (int&)a << endl;
cout << boolalpha << ( (int)a == (int&)a ) << endl; // 输出什么?
float b = 0.0f;
cout << (int)b << endl;
cout << (int&)b << endl;
cout << boolalpha << ( (int)b == (int&)b ) << endl; // 输出什么?
答:分别输出false和true。注意转换的应用。(int)a实际上是以浮点数a为参数构造了一个整型数,该整数的值是1,(int&)a则是告诉编译器将a当作整数看(并没有做任何实质上的转换)。因为1以整数形式存放和以浮点形式存放其内存数据是不一样的,因此两者不等。对b的两种转换意义同上,但是0的整数形式和浮点形式其内存数据是一样的,因此在这种特殊情形下,两者相等(仅仅在数值意义上)。
注意,程序的输出会显示(int&)a=1065353216,这个值是怎么来的呢?前面已经说了,1以浮点数形式存放在内存中,按ieee754规定,其内容为0x0000803F(已考虑字节反序)。这也就是a这个变量所占据的内存单元的值。当(int&)a出现时,它相当于告诉它的上下文:“把这块地址当做整数看待!不要管它原来是什么。”这样,内容0x0000803F按整数解释,其值正好就是1065353216(十进制数)。
通过查看汇编代码可以证实“(int)a相当于重新构造了一个值等于a的整型数”之说,而(int&)的作用则仅仅是表达了一个类型信息,意义在于为cout<<及==选择正确的重载版本。
51. 以下反向遍历array数组的方法有什么错误?[STL易]
vector array;
array.push_back( 1 );
array.push_back( 2 );
array.push_back( 3 );
for( vector::size_type i=array.size()-1; i>=0; --i ) // 反向遍历array数组
{
cout << array[i] << endl;
}
答:首先数组定义有误,应加上类型参数:vector<int> array。其次vector::size_type被定义为unsigned int,即无符号数,这样做为循环变量的i为0时再减1就会变成最大的整数,导致循环失去控制
52. 以下代码有什么问题?[STL易]
typedef vector IntArray;
IntArray array;
array.push_back( 1 );
array.push_back( 2 );
array.push_back( 2 );
array.push_back( 3 );
// 删除array数组中所有的2
for( IntArray::iterator itor=array.begin(); itor!=array.end(); ++itor )
{
if( 2 == *itor ) array.erase( itor );
}
答:同样有缺少类型参数的问题。另外,每次调用“array.erase( itor );”,被删除元素之后的内容会自动往前移,导致迭代漏项,应在删除一项后使itor--,使之从已经前移的下一个元素起继续遍历。
53. 写一个函数,完成内存之间的拷贝。[考虑问题是否全面]
答:
void* mymemcpy( void *dest, const void *src, size_t count )
{
char* pdest = static_cast<char*>( dest );
const char* psrc = static_cast<const char*>( src );
if( pdest>psrc && pdest<psrc+cout ) 能考虑到这种情况就行了
{
for( size_t i=count-1; i!=-1; --i )
pdest[i] = psrc[i];
}
else
{
for( size_t i=0; i<count; ++i )
pdest[i] = psrc[i];
}
return dest;
}
int main( void )
{
char str[] = "0123456789";
mymemcpy( str+1, str+0, 9 );
cout << str << endl;
system( "Pause" );
return 0;
}
54 线程与进程的区别
55:请你分别划划OSI的七层网络结构图,和TCP/IP的五层结构图?
56:请你详细的解释一下IP协议的定义,在哪个层上面,主要有什么作用? TCP与UDP呢?
57:请问交换机和路由器分别的实现原理是什么?分别在哪个层次上面实现的?
58:请问C++的类和C里面的struct有什么区别?
59:请讲一讲析构函数和虚函数的用法和作用?
60:全局变量和局部变量有什么区别?实怎么实现的?操作系统和编译器是怎么知道的?
61:一些寄存器的题目,主要是寻址和内存管理等一些知识。
62:8086是多少位的系统?在数据总线上是怎么实现的?
<<IBM>>
63.怎样用最快的方法判断链表是否有环?
64.c++中引用和指针有什么不同?指针加上什么限制等于引用?
65.做的项目,遇到的困难,怎样解决?
66.在房里有三盏灯,房外有三个开关,在房外看不见房内的情况,你只能进门一次,你用什么方法来区分那个开关控制那一盏灯.
67.有两根不均匀分布的香,每根香烧完的时间是一个小时,你能用什么方法来确定一段15分钟的时间.
68.一个经理有三个女儿,三个女儿的年龄加起来等于13,三个女儿的年龄乘起来等于经理自己的年龄,有一个下属已知道经理的年龄,但仍不能确定经理三个女儿的年龄,这时经理说只有一个女儿的头发是黑的,然后这个下属就知道了经理三个女儿的年龄.请问三个女儿的年龄分别是多少?为什么?
69.操作符重载
class CMyObject:pulic CObject
{
Public:
CMyObject();
CMyObject &operator=(const CMyObject &my);
private:
CString strName;
int nId:
};
请重载赋值操作符
70.链表
Struct structList
{
int value;
structList *pHead;
}
Struct LinkedList *pMyList;
请编写删除链表的头、尾和第n个节点的程序
71.用Socket API制作一个聊天程序,通讯协议使用tcp/ip。要求有简单界面即可,支持多人聊天。
72.如果有过工作经验,请说明在先前公司的工作以及离职原因(如无,请说明毕业后的个人展望)
***************************************************************************
73 对于C++中类(class) 与结构(struct)的描述正确的为:
A,类中的成员默认是private的,当是可以声明为public,private 和protected,结构中定义的成员默认的都是public;
B,结构中不允许定义成员函数,当是类中可以定义成员函数;
C,结构实例使用malloc() 动态创建,类对象使用new 操作符动态分配内存;
D,结构和类对象都必须使用new 创建;
E,结构中不可以定义虚函数,当是类中可以定义虚函数.
F,结构不可以存在继承关系,当是类可以存在继承关系.
答:A,D,F
***************************************************************************
***************************************************************************
74,两个互相独立的类:ClassA 和 ClassB,都各自定义了非景泰的公有成员函数 PublicFunc() 和非静态的私有成员函数 PrivateFunc();
现在要在ClassA 中增加定义一个成员函数ClassA::AdditionalPunction(ClassA a,ClassB b);则可以在AdditionalPunction(ClassA x,ClassB y)的实现部分(函数功能体内部)
出现的合法的表达是最全的是:
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
***************************************************************************
***************************************************************************
75,C++程序下列说法正确的有:
A,对调用的虚函数和模板类都进行迟后编译.
B,基类与子类中函数如果要构成虚函数,除了要求在基类中用virtual 声名,而且必须名字相同且参数类型相同返回类型相同
C,重载的类成员函数都必须要:或者返回类型不同,或者参数数目不同,或者参数序列的类型不同.
D,静态成员函数和内联函数不能是虚函数,友员函数和构造函数也不能是虚函数,但是析构函数可以是虚函数.
答:A
***************************************************************************
76,C++中的类与结构的区别?
77,构造函数和析构函数是否可以被重载,为什么?
78,一个类的构造函数和析构函数什么时候被调用,是否需要手工调用?
1 链接表和数组之间的区别是什么?
2 做一个链接表,你为什么要选择这样的方法?
3 选择一种算法来整理出一个链接表。你为什么要选择这种方法?现在用O(n)时间来做。
4 说说各种股票分类算法的优点和缺点。
5 用一种算法来颠倒一个链接表的顺序。现在在不用递归式的情况下做一遍。
6 用一种算法在一个循环的链接表里插入一个节点,但不得穿越链接表。
7 用一种算法整理一个数组。你为什么选择这种方法?
8 用一种算法使通用字符串相匹配。
9 颠倒一个字符串。优化速度。优化空间。
10 颠倒一个句子中的词的顺序,比如将“我叫克丽丝”转换为“克丽丝叫我”,实现速度最快,移动最少。
11 找到一个子字符串。优化速度。优化空间。
12 比较两个字符串,用O(n)时间和恒量空间。
13 假设你有一个用1001个整数组成的数组,这些整数是任意排列的,但是你知道所有的整数都在1到1000(包括1000)之间。此外,除一个数字出现两次外,其他所有数字只出现一次。假设你只能对这个数组做一次处理,用一种算法找出重复的那个数字。如果你在运算中使用了辅助的存储方式,那么你能找到不用这种方式的算法吗?
14 不用乘法或加法增加8倍。现在用同样的方法增加7倍。
.链表和数组的区别在哪里?
2.编写实现链表排序的一种算法。说明为什么你会选择用这样的方法?
3.编写实现数组排序的一种算法。说明为什么你会选择用这样的方法?
4.请编写能直接实现strstr()函数功能的代码。
5.编写反转字符串的程序,要求优化速度、优化空间。
6.在链表里如何发现循环链接?
7.给出洗牌的一个算法,并将洗好的牌存储在一个整形数组里。
8.写一个函数,检查字符是否是整数,如果是,返回其整数值。(或者:怎样只用4行代码编写出一个从字符串到长整形的函数?)
9.给出一个函数来输出一个字符串的所有排列。
10.请编写实现malloc()内存分配函数功能一样的代码。
11.给出一个函数来复制两个字符串A和B。字符串A的后几个字节和字符串B的前几个字节重叠。
12.怎样编写一个程序,把一个有序整数数组放到二叉树中?
13.怎样从顶部开始逐层打印二叉树结点数据?请编程。
14.怎样把一个链表掉个顺序(也就是反序,注意链表的边界条件并考虑空链表)?
]
答案
1、头文件中的 ifndef/define/endif 干什么用?(5分)
答:防止该头文件被重复引用。
2、#i nclude <filename.h> 和 #i nclude “filename.h” 有什么区别?(5分)
答:对于#i nclude <filename.h> ,编译器从标准库路径开始搜索 filename.h
对于#i nclude “filename.h” ,编译器从用户的工作路径开始搜索 filename.h
3、const 有什么用途?(请至少说明两种)(5分)
答:(1)可以定义 const 常量
(2)const可以修饰函数的参数、返回值,甚至函数的定义体。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。
4、在C++ 程序中调用被 C编译器编译后的函数,为什么要加 extern “C”? (5分)
答:C++语言支持函数重载,C语言不支持函数重载。函数被C++编译后在库中的名字与C语言的不同。假设某个函数的原型为: void foo(int x, int y);
该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。
C++提供了C连接交换指定符号extern“C”来解决名字匹配问题。
5、请简述以下两个for循环的优缺点(5分)
for (i=0; i<N; i++)
{
if (condition)
DoSomething();
else
DoOtherthing();
}if (condition)
{
for (i=0; i<N; i++)
DoSomething();
}
else
{
for (i=0; i<N; i++)
DoOtherthing();
}
优点:程序简洁
缺点:多执行了N-1次逻辑判断,并且打断了循环“流水线”作业,使得编译器不能对循环进行优化处理,降低了效率。优点:循环的效率高
缺点:程序不简洁
四、有关内存的思考题(每小题5分,共20分)
void GetMemory(char *p)
{
p = (char *)malloc(100);
}
void Test(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);
}
请问运行Test函数会有什么样的结果?
答:程序崩溃。
因为GetMemory并不能传递动态内存,
Test函数中的 str一直都是 NULL。
strcpy(str, "hello world");将使程序崩溃。
char *GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char *str = NULL;
str = GetMemory();
printf(str);
}
请问运行Test函数会有什么样的结果?
答:可能是乱码。
因为GetMemory返回的是指向“栈内存”的指针,该指针的地址不是 NULL,但其原现的内容已经被清除,新内容不可知。
void GetMemory2(char **p, int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
请问运行Test函数会有什么样的结果?
答:
(1)能够输出hello
(2)内存泄漏
void Test(void)
{
char *str = (char *) malloc(100);
strcpy(str, “hello”);
free(str);
if(str != NULL)
{
strcpy(str, “world”);
printf(str);
}
}
请问运行Test函数会有什么样的结果?
答:篡改动态内存区的内容,后果难以预料,非常危险。
因为free(str);之后,str成为野指针,
if(str != NULL)语句不起作用。
27 费波那其数列,1,1,2,3,5……编写程序求第十项。可以用递归,也可以用其他方法,但要说明你选择的理由。
-------------------------------------------------------------------------------------
#i nclude <stdio.h>
#i nclude <cstdlib>
int Pheponatch(int);
int Pheponatch2(int);
int main()
{
printf("The 10th is %d",Pheponatch2(20));
system("pause");
return 0;
}
//递归算法
int Pheponatch(int N)
{
if( N == 1 || N == 2)
{
return 1;
}
else
return Pheponatch( N -1 ) + Pheponatch( N -2 );
}
//非递归算法
int Pheponatch2(int N)
{
int x = 1, y = 1, temp;
int i = 2;
while(true)
{
temp = y;
y = x + y;
x = temp;
i++;
if( i == N )
break;
}
return y;
}
25.完成下列程序
*
*.*.
*..*..*..
*...*...*...*...
*....*....*....*....*....
*.....*.....*.....*.....*.....*.....
*......*......*......*......*......*......*......
*.......*.......*.......*.......*.......*.......*.......*.......
#i nclude <stdio.h>
#define N 8
int main()
{
int i;
int j;
int k;
---------------------------------------------------------
| |
| |
| |
---------------------------------------------------------
return 0;
}
#i nclude <stdio.h>
#i nclude <iostream.h>
#define N 8
int main()
{
int i;
int j;
int k;
for(i=N; i>=1; i--)
{
for(j=0; j<N-i+1; j++)
{
cout<<"*";
for(k=1; k<N-i+1; k++)
cout<<".";
}
cout<<"\n";
}
return 0;
}
"28 下列程序运行时会崩溃,请找出错误并改正,并且说明原因。"
// void append(int N) ;
//指针没有初始化:
//NewNode->left=NULL;
//NewNode->right=NULL;
#i nclude <stdio.h>
#i nclude <malloc.h>
`
typedef struct TNode{
TNode* left;
TNode* right;
int value;
} TNode;
TNode* root=NULL;
void append(int N);
int main()
{
append(63);
append(45);
append(32);
append(77);
append(96);
append(21);
append(17); // Again, 数字任意给出
return 0;
}
void append(int N)
{
TNode* NewNode=(TNode *)malloc(sizeof(TNode));
NewNode->value=N;
NewNode->left=NULL;
NewNode->right=NULL;
if(root==NULL)
{
root=NewNode;
return;
}
else
{
TNode* temp;
temp=root;
while((N>=temp->value && temp->left!=NULL) || (N<temp->value && temp->right!=NULL))
{
while(N>=temp->value && temp->left!=NULL)
temp=temp->left;
while(N<temp->value && temp->right!=NULL)
temp=temp->right;
}
if(N>=temp->value)
temp->left=NewNode;
else
temp->right=NewNode;
return;
}
}
算法:
1.什么是NPC,NP-Hard?
2.起泡排序的时间复杂度是多少?
说出至少一个比它更快的算法;
排序的极限时间复杂度是多少?
3.有一个链表,如何判断它是一个循环链表?
如果链表是单向的呢?
如果出现循环的点可能在任意位置呢?
如果缓存空间是有限的,比如是一个常数呢?
如果只能使用2个缓存呢?
4.有一个文件,保存了若干个整数,如何以平均的概率随机得到其中的一个整数?
如果整数的个数是未知的呢?
如果整数是以字符串形式存放,如:(即如何得到随机的一个字符串)
123<enter>
-456<enter>
…
如果只允许便历文件一次呢?
5.用两组数据,都在内存中,对它们排序分别需要1和2分钟;那么使用两个线程一起排序,大概需要多少时间?
C/C++:
1.C与C++的异同,优劣;
2.C,C++,VC,BC,TC的区别;
3.C++中try…catch关键字的用法与优点;
4.枚举的用法,以及它与宏的区别;
5.const的用法,以及声明const变量与宏的区别;
const的用法有四种:
区别:const常量有数据类型, 而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只能进行字符替换,没有类型
安全检查。而且字符替换可能会带来料想不到的边界效应。
有些集成化工具可以对const常量进行调试, 但不能对宏量进行调试。
6.C++中引用与指针的区别;
答:1 引用实际上是所引用的对象或变量的别名,而指针是包含所指向对象或变量 的地址的变量。
2 引用在定义时必须初始化,而指针在定义时不初始化。
3 不可以有努NULL的引用,而可以有指向NULL的指针。
4 引用在初始化后不可以改变引用关系,而指针可以随时指向其他对象(非 const指针)。
7.C++中virtual与inline的含义分别是什么?
答:在基类成员函数的声明前加上virtual关键字,意味着将该成员函数声明为虚函数。
inline与函数的定义体放在一起,使该函数称为内联。inline是一种用于实现的关键字,而不是用于声明的关键字。
虚函数的特点;如果希望派生类能够重新定义基类的方法,则在基类中将该方法定义为虚方法,这样可以启用动态联编。
内联函数的特点;使用内联函数的目的是为了提高函数的运行效率。内联函数体的代码不能过长,因为内联函数省去调用函数
的时间是以代码膨胀为代价的。内联函数不能包含循环语句,因为执行循环语句要比调用函数的开销大。
一个函数能否即是虚函数又是内联函数?
8.以下关键字的含义与用法:
extern,extern “C”,static,explicit,register,#undef,#ifndef
9.什么是函数重载与覆盖?
为什么C不支持函数重载?
为什么C++能支持函数重载?
10.VC中,编译工具条内的Debug与Release选项是什么含义?
11.编写my_memcpy函数,实现与库函数memcpy类似的功能,不能使用任何库函数;
void* mymemcpy(void* pvTo, const char* pvFrom, size_t size)
{
assert((dest != NULL) && (src != NULL));
byte* psTo = (byte*)pvTo;
byte* psFrom = (byte*)pvFrom;
while (size-- > 0)
{
*psTo++ = *psFrom++;
}
return pvTo;
}
12.编写my_strcpy函数,实现与库函数strcpy类似的功能,不能使用任何库函数;
答:char* my_strcpy(char* strdest, const char* strsrc)
{
assert(strdest != NULL) && (strsrc != NULL))
char* address = strdest;
while((*strdest++ = *strsrc++) != NULL)
return address;
}
13.编写gbk_strlen函数,计算含有汉字的字符串的长度,汉字作为一个字符处理;
已知:汉字编码为双字节,其中首字节<0,尾字节在0~63以外;(如果一个字节是-128~127)
14.函数assert的用法?
答:断言assert是仅在debug版本起作用的宏,用于检查“不应该“发生的情况。程序员可以把assert看成一个
在任何系统状态下都可以安全使用的无害测试手段。
15.为什么在头文件的最前面都会看到这样的代码:
#ifndef _STDIO_H_
#define _STDIO_H_
16.为什么数组名作为参数,会改变数组的内容,而其它类型如int却不会改变变量的值?
答:当数组名作为参数时,传递的实际上是地址。而其他类型如int作为参数时,由于函数参数值实质上是实参的一份拷贝,被调
函数内部对形参的改变并不影响实参的值。
1.实现双向链表删除一个节点P,在节点P后插入一个节点,写出这两个函数。
2.写一个函数,将其中的\t都转换成4个空格。
3.Windows程序的入口是哪里?写出Windows消息机制的流程。
4.如何定义和实现一个类的成员函数为回调函数?
5.C++里面是不是所有的动作都是main()引起的?如果不是,请举例。
6.C++里面如何声明const void f(void)函数为C程序中的库函数?
7.下列哪两个是等同的
int b;
A const int* a = &b;
B const* int a = &b;
C const int* const a = &b;
D int const* const a = &b;
8.内联函数在编译时是否做参数类型检查?
void g(base & b){
b.play;
}
void main(){
son s;
g(s);
return;
}
3、WinMain
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
MSRA Interview Written Exam(December 2003,Time:2.5 Hours)
1写出下列算法的时间复杂度。
(1)冒泡排序;
(2)选择排序;
(3)插入排序;
(4)快速排序;
(5)堆排序;
(6)归并排序;
2写出下列程序在X86上的运行结果。
struct mybitfields
{
unsigned short a : 4;
unsigned short b : 5;
unsigned short c : 7;
}test
void main(void)
{
int i;
test.a=2;
test.b=3;
test.c=0;
i=*((short *)&test);
printf("%d\n",i);
}
3写出下列程序的运行结果。
unsigned int i=3;
cout<<i * -1;
4写出下列程序所有可能的运行结果。
int a;
int b;
int c;
void F1()
{
b=a*2;
a=b;
}
void F2()
{
c=a+1;
a=c;
}
main()
{
a=5;
//Start F1,F2 in parallel
F1(); F2();
printf("a=%d\n",a);
}
5考察了一个CharPrev()函数的作用。
6对 16 Bits colors的处理,要求:
(1)Byte转换为RGB时,保留高5、6bits;
(2)RGB转换为Byte时,第2、3位置零。
7一个链表的操作,注意代码的健壮和安全性。要求:
(1)增加一个元素;
(2)获得头元素;
(3)弹出头元素(获得值并删除)。
8一个给定的数值由左边开始升位到右边第N位,如
0010<<1 == 0100
或者
0001 0011<<4 == 0011 0000
请用C或者C++或者其他X86上能运行的程序实现。
附加题(只有在完成以上题目后,才获准回答)
In C++, what does "explicit" mean? what does "protected" mean?
普天c++笔试
我解答的普天C++笔试题
普天是南京一家通信公司,全称为:南京普天通信股份有限公司,公司网址为:http://www. 网上流传一套普天C++笔试题,我将我做的答案公布与此,仅供参考。
1.实现双向链表删除一个节点P,在节点P后插入一个节点,写出这两个函数; 答:
//假设线性表的双向链表存储结构 typedef struct DulNode{ struct DulNode *prior; //前驱指针 ElemType data; //数据 struct DulNode *next; //后继指针 }DulNode,*DuLinkList; //删除操作 Status ListDelete_DuL(DuLinkList &L,int i,ElemType &e) { if(!(p=GetElemP_DuL(L,i))) //此处得到i位置的节点指针,如果有需要也得写出具体函数实现 return ERROR; e=p->data; p->prior->next=p->next; p->next->prior=p->pror; free(p); return OK; } //插入操作 Status ListInsert_DuL(DuLinkList &L,int i,ElemType &e) { if(!(p=GetElemP_DuL(L,i))) return ERROR; if(!(s=(DuLinkList)malloc(sizeof(DuLNode)))) return ERROR;
s->data=e; s->prior=p->prior; p->prior->next=s; s->next=p; p->prior=s; return OK; }
2.写一个函数,将其中的\t都转换成4个空格。 答: 该函数命名为convert,参数的意义为: *strDest目的字符串,*strSrc源字符串,length源字符串的长度 函数实现为:
char* convert(char *strDest, const char *strSrc,int length) { char * cp = strDest; int i=0; while(*strSrc && i<length) // 跳出条件 { if (*strSrc=='\t') //将\t转换成4个空格 { for(int j=0;j<4;j++) *cp++=' '; } else //否则直接拷贝 *cp++=*strSrc; strSrc++; i++; } return strDest; }
3.Windows程序的入口是哪里?写出Windows消息机制的流程。 答: Windows程序的入口是WinMain函数 消息机制:系统将会维护一个或多个消息队列,所有产生的消息都会被放入或是插入队列中。系统会在队列中取出每一条消息,根据消息的接收句柄而将该消息发送给拥有该窗口的程序的消息循环。每一个运行的程序都有自己的消息循环,在循环中得到属于自己的消息并根据接收窗口的句柄调用相应的窗口过程。而在没有消息时消息循环就将控制权交给系统。
4.如何定义和实现一个类的成员函数为回调函数? 答: 所谓的回调函数,就是预先在系统的对函数进行注册,让系统知道这个函数的存在,以后,当某个事件发生时,再调用这个函数对事件进行响应。 定义一个类的成员函数时在该函数前加CALLBACK即将其定义为回调函数,函数的实现和普通成员函数没有区别
---------------------------------------------- 插播条广告:版权所有:朱科 欢迎光临我的网站:www.,转贴勿删哦 ----------------------------------------------
5.C++里面是不是所有的动作都是main()引起的?如果不是,请举例。 答:不是,比如中断引起的中断处理不是直接由main()引起的,而是由外部事件引起的。
6.C++里面如何声明const void f(void)函数为C程序中的库函数? 答:在该函数前添加extern “C”声明
7.下列哪两个是等同的 int b; A const int* a = &b; B const* int a = &b; C const int* const a = &b; D int const* const a = &b; 答: 各式表示的意思分别为: A const int* a = &b; //*a是const,但指针a可变 B const* int a = &b; //a是const,但*a可变 C const int* const a = &b; //a和*a都是const,常量和指针的值都不能改变 D int const* const a = &b; //a和*a都是const,常量和指针的值都不能改变 因此C,D两者是相同的。 总结个技巧:如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。
8. 内联函数在编译时是否做参数类型检查? 答:做类型检查,因为内联函数就是在程序编译时,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体来代替。
zjh848 发表于 >2006-3-30 7:03:18 [全文] [评论] [引用] [推荐] [档案] [推给好友] [收藏到网摘]
|
|
2006-3-30
C/C++笔试题
1、字符串比较,同strcmp的功能,以下为仿函数版本。 struct StringCmp { int operator()( const char* lpszStr1, const char* lpszStr2 { if ( NULL == lpszStr1 { if ( NULL == lpszStr2 return 0; return -1; } if ( NULL == lpszStr2 return 1;
for ( ; ( 0 != ( ( *lpszStr1 & ( *lpszStr2 ; ++ lpszStr1, ++ lpszStr2 { if ( *lpszStr1 < *lpszStr2 return -1; if ( *lpszStr1 > *lpszStr2 return 1; } if ( 0 != *lpszStr2 return -1; if ( 0 != *lpszStr1 return 1; return 0; } };
2. 4、判断字符串是否为回环串,类似于"abcdcba"(?),这个可能挺简单,但是好像很多大公司出的 笔试题似乎都很简单,不知其考察点在于什么。。。 template < class Character = char > struct IsCircleString { typedef Character char_t; bool operator()( const char_t* pStr { const char_t* pLast = pStr; for ( ; 0 != *pLast; ++ pLast {} if ( ( ( pLast - pStr & 0x1 == 0 return false;//偶数即返回false -- pLast; for ( ; pStr < pLast; ++ pStr, -- pLast { if ( *pStr != *pLast return false; } return true; } };
3.变量的声明和定义有什么区别?
答: 变量声明只是给编译器一个提示,和运行环境无关;而变量定义是分配了具体的内存空间。 比如: extern int a; //变量声明 int b; //变量定义 4.请写出下面代码在 32 位平台上的运行结果,并说明 sizeof 的性质:
#include <stdio.h> #include <stdlib.h>
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 ; } 答: 在32位系统下(如WIN32),指针长度为32位,并且, a是一个有30个元素的字符型数组;b是一个字符串指针;a[3]是字符型;b+3是指针;*(b+4)是字符型。 因此输出: 30、4、1、4、1 一、 单项选择题(从四个备选答案中选择一个正确答案,每小题1分,共20分) 1. C++中,关键字struct和class的区别仅仅在于( C )。
(A)struct 用来定义结构体, 而class用来定义类;
(B)struct 用来定义类, 而class用来定义类结构体;
(C)struct定义的类的缺省成员为公有的,而class定义的类的缺省成员为私有的;
(D)struct定义的类的成员须全部为公有的,而class定义的类的成员可以为私有的;
2. 以下程序执行后,输出结果为( C .
#i nclude
int Var=3 ;
void main(void)
{ int Var=10;
::Var++;
cout<<”Var=”< }
(A)Var=11, ::Var=11 (B)Var=11, ::Var=3
(C)Var=10, ::Var=4 (D)Var=4, ::Var=10
3. 抽象基类是指( C )。
(A)嵌套类 (B)派生类
(C)含有纯虚函数 (D)多继承类
4.如果有#define AREA(a,b)a+b 则语句int s=AREA(3,4)*AREA(3,4)执行后变量s值为( D )。
(A) 24 (B)49 (C)144 (D)19
5. C++中条件表达式的值为( C )。
(A)–1或者+1 (B)–231~231 –1 (C)0或者1 (D) 0~231–1
6. 现在有以下语句:
struct MyBitType
{ int a:3;
unsigned b:3;
unsigned c:20;
int d;
};
int sz=sizeof(MyBitType);
则执行后,变量sz的值将得到( B 。
(A)2 (B)8 (C)28 (D)58
7. 假设有一个C++类名为Country, 则此类的析构函数为( C .
(A)::Country() (B)void ~Country(void)
(C)~Country() (D)void ~Country()
8. 如果定义一个C++类CDate, 语句“CDate *p = new CDate;”的含义是( A )。
(A)调用CDate类的缺省构造函数从内存中分配一个CDate类型的对象,并将该对象地址赋值给指针p;
(B)调用CDate类的拷贝构造函数从内存中分配一个CDate类型的对象,并将该对象地址赋值给指针p;
(C)调用CDate类的析构函数从内存中分配一个CDate类型的对象,并将该对象地址赋值给指针p;
(D)从内存中释放指针p所指向的CDate类的对象;
9.如果有一个类CRect及语句“CRect x1, x2;” 要使语句 “x1=x2;”合法,可在类中定义成员函数( C )。
(A) int operator(x2) (B)int operator=(x2)
(C) void operator=(CRect & ; (D) void operator=()
10. 结构体变量S实际所占内存的大小为( A )字节。
(A)sizeof(S) (B)strlen(S)
(C)结构体中最长成员的长度 (D)结构体中最短成员的长度
11.在C++中,下列算符( D )不能重载。
(A)<< (B)>> (C)delete (D)::
12.下列正确的是( D )
(A)结构不能有构造函数、析构函数; (B)缺省时类的成员是公有的;
(C)类中如果定义了析构函数,则必须定义构造函数;
(D)缺省时结构的成员是公有的;
13. 下列关于静态数据成员正确的是( B )
(A)可以通过this指针访问静态数据; (B)可以用类名和作用域访问静态数据;
(C)静态数据在类内声明并初始化; (D)只能由该类的静态成员函数访问;
14. 下列关于友元正确的说法是( D )
(A)友元只能在类的public区声明;(B)友元具有this指针;
(C)类的成员函数不能声明为另一个类的友元;
(D)一个函数如果被声明为一个类的友元,则该函数具有访问该类私有成员的权利。
15. 基类的( A 在派生类内不能被访问。
(A)私有成员 (B)保护成员
(C)公有数据成员 (D)公有静态数据成员
16. 下列关于运算符重载的描述中正确的是( D )
(A)运算符重载可以改变该运算符的优先级;
(B)运算符重载可以改变该运算符目数,即该算符运算的操作数个数;
(C)运算符重载函数只能在类中定义;
(D)new和delete允许重载;
17.左值是指( A )
(A)赋值算符左边的变量; (B)赋值算符左边的表达式的值;
(D)出现在赋值算符右边的表达式的值;
(E)二元算符左边表达式的值;
18. 下列为纯虚函数的正确声明的是( B )
(A)void virtual print()=0; (B)virtual void print()=0;
(C)virtual void print(){ }; (D)virtual void print();
19. 如果在类对象a的类中重载运算符“+”,则a+5的显示调用方式为( C )
(A)a.operator(5) (B)a->operator+(5);
(C)a.operator+(5) (D)5.operator+(a)
20.一个类如果有一个以上的基类就叫做( B )。
(A)循环继承 (B)单继承
(C)非法继承 (D)多继承
二、 多项选择题(从五个备选答案中选择2~5个正确答案,每小题2分,共10分) 1. 如果已定义了一个C++类CMyList并有以下语句:
CMyList list(3);
以下说法正确的是( AC )。
(A)该语句会创建一个CMyList类的一个对象;
(B)该语句会创建一个CMyList类的3个对象;
(C)必须为类CMyList定义一个构造函数;
(D)必须为类CMyList定义一个析构函数;
(E) 必须定义函数CMyList list(int);
2. 以下说法正确的是( ABCDE )。
(A)内联(inline)函数改善了函数调用的执行效率。
(B)类A的友元(friend)函数可以访问类A的私有成员。
(C)类A的友元(friend)类B可以访问类A的私有成员。
(D)类A的静态数据成员为类A的所有对象所共享。
(E)类A的静态成员函数没有传递this 指针作为参数。
3.类B从类A派生,则类B可以访问类A中的( AC )成员。
(A)public成员 (B)private成员 (C)protected成员
(D)数据成员 (E)函数成员
4. 面向对象的程序设计语言具有( ABE )等共同特性。
(A)封装性 (B)多态性 (C)简单性 (D)复杂性
(E)继承性
5. 现有一个程序如下:
#i nclude
class A
{ public:
void f(){ cout<< "A::f()"< };
class B
{ public:
void f(){ cout<< "B:f()"< void g(){ cout<< "B:g()"< };
class C ublic A, public B
{ public:
void g(){ cout<<"C::g()"< void h()
{ cout<<"C::h()"< f(); //语句1
}
};
void main()
{ C obj;
obj.f(); //语句2
obj.A::f(); //语句3
obj.B::f(); //语句4
obj.g(); //语句5
}
则编译时会产生错误的语句有( AB 。
(A)语句1 (B)语句2 (C)语句3
(D)语句4 (E)语句5
三、 判断分析题(正确的画上√,错误的画上×,每小题1分,共10分) 1.如果一个类的所有对象都共享某一个变量,则应当将该变量定义为该类的static成员。 ( √ )
2.语句“ typedef struct _MYSTRUC { int x; int y; double z; } MYSTRUC; ”是非法语句。 ( ×
3.语句“ int (*p)(int x, int y);”说明了p是一个指向整数的指针。 ( ×
4.Visual C++集成开发环境中,一个Workspace中只能创建一个Project。 ( × )
5.能访问一个类CMyClass中的private成员的可以是类CMyClass的成员函数,友元函数和友元类中的函数。 ( √ )
6. 所有的MFC应用程序都必须有一个且只有一个CWinApp对象。 ( √ )
7.C++中的多态性就是指在编译时,编译器对同一个函数调用,根据情况调用不同的实现代码。 ( × )
8.在for循环中,是先执行循环体后再判断循环条件。 ( × )
9.C++中,如果条件表达式值为-1, 则表示逻辑为假。 ( × )
10. 在C++中用new分配的内存空间,在不需要时一般用free将该空间释放。 ( ×
四、 填空题(每空2分,共20分) 1.以下函数完成求表达式 的值,请填空使之完成此功能。
float sum( float x
{ float s=0.0;
int sign=1;
float t=1.0;
for(int i=1; i<=100; i++)
{
t=t*x;
s=s+-sign*i/(t+sign*i);
sign=-sign;
}
return s;
}
2.以下程序中实现类CSort, 完成对其成员p所指向的整数数组进行从小到大排序,该数组的元素个数由num表示,请填空完善该程序。
#i nclude
class CSort
{
int *p;
int num;
public:
void Order();
CSort(int *, int);
void Disp();
};
CSort::CSort(int *arry, int n)
(arry), num(n)
{ }
void CSort::Order() //函数Order原型
{ int m, tmp;
for(int i=0; i { m=i;
for(int j=i+1; j { if(p[j] m=j;
}
if(m!=i)
{ tmp=p[i];
p[i]=p[m];
p[m]=tmp;
}
}
}
void CSort: isp()
{ for(int i=0; i cout< cout< }
void main(
{ static int a[]={10, -15, -3, 5, -4, 7,2};
CSort obj(a,2);
obj.Disp(); //应输出一行:10,-15,-3,5,-4,7,2
obj.Order(); //对数组排序
obj.Disp(); //应输出一行:-15,-4,-3,2,5,7,10
}
3.以下函数完成求两个数n1和n2的最大公约数。
#i nclude
int fac(int n1, int n2)
{ int tmp;
if( n1 < n2
{ tmp=n1;
n1=n2 ;
n2=tmp ;
}
while(n1%n2!=0)
{ tmp=n1%n2; n1=n2; n2=tmp;
}
return n2;
}
五、 阅读程序题(每个小题5分,共20分) 1.阅读以下程序,概括地写出程序的功能。
#i nclude
double Exp(double x)
{ double sum=1.0;
double term=x;
double i=1 ;
while (term>=1.0E-8)
{ sum+=term ;
i++;
term=term*x/i ;
}
return sum ;
}
void main()
{ double s;
s=Exp(1.0)+Exp(2.0);
cout.precision(8);
cout<<"s="< }
zz
2. 阅读程序,写出程序执行时输出结果。
#i nclude
const int SIZE=10;
class stack
{ char stck[SIZE];
int top;
public:
void init();
void push(char ch);
char pop();
};
void stack::init()
{ top=0; }
void stack: ush(char ch)
{ if(top==SIZE)
{ cout<<"Stack is full.\n";
return ;
}
stck[top++]=ch;
}
char stack: op()
{ if(top==0)
{ cout<<"Stack is empty.\n";
return 0;
}
return stck[--top];
}
void main()
{ stack s1, s2;
s1.init();
s2.init();
s1.push('a');
s1.push('b');
s1.push('c');
s2.push('x');
s2.push('y');
s2.push('z');
for(int i=0; i<3; i++)
cout<<"Pop s1:"< for(i=0; i<3; i++)
cout<<"Pop s2:"< }
程序结果:
Pop s1: c
Pop s1: b
Pop s1: a
Pop s2: z
Pop s2: y
Pop s2: z
3.阅读程序,写出程序运行时输出结果。
#i nclude
class Tdate
{ public:
Tdate();
Tdate(int d);
Tdate(int m, int d);
Tdate(int m, int d, int y);
protected:
int month;
int day;
int year;
};
Tdate::Tdate()
{ month=4;
day=15;
year=1995;
cout< }
Tdate::Tdate(int d)
{ month=4;
day=d;
year=1996;
cout< }
Tdate::Tdate(int m, int d)
{ month=m;
day=d;
year=1997;
cout< }
Tdate::Tdate(int m, int d, int y)
{ month=m;
day=d;
year=y;
cout< }
void main()
{ Tdate aday;
Tdate bday(10);
Tdate cday(2,12);
Tdate dday(1,2,1998);
}
运行结果:
4/15/1995
4/10/1996
2/12/1997
1/2/1998
4.阅读程序,写出程序运行时输出结果。
#i nclude
#i nclude
class shape
{ public:
shape(double x, double y):xCoord(x), yCoord(y){}
virtual double Area()const {return 0.0; }
protected:
double xCoord, yCoord;
};
class AA ublic shape
{ public:
AA(double x, double y, double r): shape(x,y), rad(r){}
virtual double Area()const { return 3.0 * rad * rad; }
protected:
double rad;
};
class BB ublic shape
{ public:
BB(double x1, double y1, double x2, double y2)
:shape(x1, y1), x2Coord(x2), y2Coord(y2){ }
virtual double Area()const;
protected:
double x2Coord, y2Coord;
};
double BB:Area()const
{ return fabs((xCoord-x2Coord)* (yCoord - y2Coord));
//库函数fabs(double t)求得t的绝对值
}
void fun(const shape& sp)
{ cout< }
void main()
{ AA aa(2.0, 5.0, 4.0);
fun(aa);
BB bb(2.0, 8.0, 12.0, 17.0);
fun(bb);
}
运行结果:
48
30
六、 编写程序题(每小题10分,共20分) 1.编写一个函数int Judge(int *pArray, int n),判断一个n×n二维整数数组pArray 是否为“魔方阵”,若是返回1,否则返回0。所谓 魔方阵就是将1到n2的各个数字组成的方阵,它的每一行、每一列以及两个对角线上数字之和均相等。例如,3×3的 中,A是魔方阵,而B不是魔方阵。然后在主程序中调用Judge函数判断数组A是否为魔方阵。
参考程序
#i nclude
int Judge(int *pArray, int n)
{ int s1, s2, s3,s4,sum=0;
int *p=pArray;
for(int i=1; i<= n*n; i++)
{ int Found=0; //为0,不在方阵中;
for(int j=0; j if(p[j]==i)
{ Found=1; //为1,在方阵中
break;
}
if(Found==0) return 0; // 值为 i 的元素不在数组中,显然不是魔方阵
}
for( i=1; i<=n*n; i++)
sum=sum+i;
sum=sum / n; // 各行、各列、对角线元素应当得到的和
s3=0;
s4=0;
for( i=0; i { s1=0, s2=0;
p=pArray;
for(int j=0; j { s1=s1+p[i*n+j]; //第i行的元素和
s2=s2+p[j*n+i]; //第i列的元素和
}
if ( s1!=sum)
return 0;
if ( s2!=sum)
return 0;
s3=s3+pArray[i*n+i]; // 对角线一元素和
s4=s4+pArray[i*n+(n-1-i)]; // 对角线二元素和
}
if(s3!=sum)
return 0;
if(s4 != sum)
return 0;
return 1;
}
void main()
{ int Array[3][3]={{ 8, 1, 6},{ 3, 5, 7},{ 4, 9, 2}};
if(Judge((int*)Array, 3))
cout<<"Yes, it's a magic array"< else
cout<<"No, it isn't a magic array"< }
|
|
C++知识点
一、#include "filename.h"和#include <filename.h>的区别
#include "filename.h"是指编译器将从当前工作目录上开始查找此文件
#include <filename.h>是指编译器将从标准库目录中开始查找此文件
二、头文件的作用
加强安全检测
通过头文件可能方便地调用库功能,而不必关心其实现方式
三、* , &修饰符的位置
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名
四、if语句
不要将布尔变量与任何值进行比较,那会很容易出错的。
整形变量必须要有类型相同的值进行比较
浮点变量最好少比点,就算要比也要有值进行限制
指针变量要和NULL进行比较,不要和布尔型和整形比较
五、const和#define的比较
const有数据类型,#define没有数据类型
个别编译器中const可以进行调试,#define不可以进行调试
在类中定义常量有两种方式
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值;
2、 用枚举代替const常量。
六、C++函数中值的传递方式
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference)
void fun(char c) //pass by value
void fun(char *str) //pass by pointer
void fun(char &str) //pass by reference
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构
函数的类型不能省略,就算没有也要加个void
七、函数体中的指针或引用常量不能被返回
Char *func(void)
{
char str[]="Hello Word";
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉
return str;
}
函数体内的指针变量并不会随着函数的消亡而自动释放
八、一个内存拷贝函数的实现体
void *memcpy(void *pvTo,const void *pvFrom,size_t size)
{
assert((pvTo!=NULL)&&(pvFrom!=NULL));
byte *pbTo=(byte*)pvTo; //防止地址被改变
byte *pbFrom=(byte*)pvFrom;
while (size-- >0)
pbTo++ = pbForm++;
return pvTo;
}
九、内存的分配方式
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。
十、内存分配的注意事项
用new或malloc分配内存时,必须要对此指针赋初值。
用delete 或free释放内存后,必须要将指针指向NULL
不能修改指向常量的指针数据
十一、内容复制与比较
//数组......
char a[]="Hello Word!";
char b[10];
strcpy(b,a);
if (strcmp(a,b)==0)
{}
//指针......
char a[]="Hello Word!";
char *p;
p=new char[strlen(a)+1];
strcpy(p,a);
if (strcmp(p,a)==0)
{}
十二、sizeof的问题
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节
char a[]="Hello World!"
char *p=a;
count<<sizeof(a)<<end; //12字节
count<<sizeof(p)<<endl; //4字节
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4
void fun(char a[1000])
{
count<<sizeof(a)<<endl; //输出4而不是1000
}
十三、关于指针
1、 指针创建时必须被初始化
2、 指针在free 或delete后必须置为NULL
3、 指针的长度都为4字节
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如
char *p=new char[100];
strcpy(p,"Hello World");
delete []p; //注意前面的[]号
p=NULL;
5、数组指针的内容不能超过数组指针的最大容易。
如:
char *p=new char[5];
strcpy(p,"Hello World"); //报错 目标容易不够大
delete []p; //注意前面的[]号
p=NULL;
十四、关于malloc/free 和new /delete
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。
l 注意:malloc/free是库函数,new/delete是运算符
l malloc/free不能执行构造函数与析构函数,而new/delete可以
l new/delete不能在C上运行,所以malloc/free不能被淘汰
l 两者都必须要成对使用
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理
十五、C++的特性
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制
重载和内联:即可用于全局函数,也可用于类的成员函数;
Const和Virtual:只可用于类的成员函数;
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。
覆盖是指派生类函数覆盖基类函数
函数名相同;
参数相同;
基类函数必须有Virtual关键字;
不同的范围(派生类和基类)。
隐藏是指派生类屏蔽了基类的同名函数相同
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。
Const:const是constant的缩写,"恒定不变"的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。
1、 参数做输入用的指针型参数,加上const可防止被意外改动。
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如:
将void Func(A a) 改为void Func(const A &a)。
而void func(int a)就没必要改成void func(const int &a);
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体;
十六、extern"C"有什么作用?
Extern "C"是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren "c"后,C++就能直接调用C函数了。
Extern "C"主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern "c" 关键字即可。
十七、构造函数与析构函数
派生类的构造函数应在初始化表里调用基类的构造函数;
派生类和基类的析构函数应加Virtual关键字。
不要小看构造函数和析构函数,其实编起来还是不容易。
#include <iostream.h>
class Base
{
public:
virtual ~Base() { cout<< "~Base" << endl ; }
};
class Derived : public Base
{
public:
virtual ~Derived() { cout<< "~Derived" << endl ; }
};
void main(void)
{
Base * pB = new Derived; // upcast
delete pB;
}
输出结果为:
~Derived
~Base
如果析构函数不为虚,那么输出结果为
~Base