整理的C++笔试题

1,switch(c)语句中,才不可以是什么类型()A ,int    B,long      C,char                D,float

答案:D。c只能是整型。整型包括short、int、long和signed、unsigned的排列组合以及bool和char(signed和unsigned)共13种类型。

2,i=4,那么语句:j=i+++i;执行后的结果应该是()A  i=4,j=6    B i=5,j=5            C I=5,j=6              D  i=6,j=6

答案:B。很显然。

3,下面哪个操作符不能重载()

答案:算术运算符:+,-,*,/,%,++,--;
位操作运算符:&,|,~,^(位异或),<<(左移),>>(右移)
逻辑运算符:!,&&,||;
比较运算符:<,>,>=,<=,==,!=;
赋值运算符:=,+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>=;
其他运算符:[],(),->,,(逗号运算符),new,delete,new[],delete[],->*。 

不能重载的5个运算符
.  
?: 
siezof 
::     
.*  


4,下面说法正确的是()

A  在C++语言中new和malloc都是在堆上进行动态的内存操作,可以互相代替

B  c++语言重载是只子类重新定义父类的虚函数的方法

C  c++语言函数既可以嵌套定义又可以递归调用

D  在c++语言中调用函数时,只能把实参的值传给形参,形参的值不能传给实参

答案:D。malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。new可以认为是malloc加构造函数的执行。new出来的指针是直接带类型信息的。而malloc返回的都是void*指针。new delete在实现上其实调用了malloc,free函数。new建立的对象你可以把它当成一个普通的对象,用成员函数访问,不要直接访问它的地址空间;malloc分配的是一块内存区域,就用指针访问好了,而且还可以在里面移动指针.new 建立的是一个对象;alloc分配的是一块内存.

        C++中函数只能递归调用(有时也说嵌套调用),但不能嵌套定义。《Cpp大学教程(第五版)》在第三章的类和对象介绍第61页讲到:常见的编程错误3.3  将一个函数定义在另一个函数内部是一个语法错误。

5,派生类的对象对它的基类成员中,()是可以访问的。A  公有继承的公有成员  B 公有继承的私有成员  C 公有继承的保护成员  D 私有继承的公有成员

答案:A

1,求下面函数的返回值,当x=8421.
int func(x)
{
int countx = 0;
while(x)
{
countx ++;
x = x&(x-1);
}
return countx;
}

答案:将x转化为2进制,看含有的1的个数。

6,程序的局部变量存在于( )中,全局变量存在于( )中,动态申请数据存在于( )中?

答案;栈                静态(全局)数据区                    堆

7,char  *p="helloworld";  sizeof(p)的值是:4.

8.C++通过()可以把类型定义域参数,从而实现了真正的代码可重用性。

答案:模板。

8.template <class T>

9,继承

10,线程与进程的区别和联系?线程是否具有相同的堆栈?

答案:进程是死的,只是一些资源的集合,真正的程序执行都是线程来完成的,程序启动的时候操作系统就帮你创建了一个主线程。每个线程有自己的堆栈。

11,static局部变量和普通局部变量有什么区别?

答案:static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值;把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。

补充:把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。static全局变量只初使化一次,防止在其他文件单元中被引用;非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。

补充;static函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件。static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝。

12,友元函数与成员函数的区别是什么?

答案:成员函数是类定义的一部分,通过特定的对象来调用。成员函数可以隐式访问调用对象的成员,而无须使用成员操作符。友元函数不是类的组成部分,因此被称为直接函数调用。友元函数不能隐式访问类成员,而必须将成员操作符用于作为参数传递的对象。友元函数是非成员函数,可以在他的函数体中可以通过对象名访问类的的私有和保护成员,一般情况下,它在类中声明,在类外实现。

13,在C++程序中调用被C编译器编译后的函数,为什么要加extern “C"?

答案:作为extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。可以用一句话概括extern “C”这个声明的真实目的:实现C++与C及其它语言的混合编程。

14,下面的代码:问题出在哪里,怎么改?

#include<stdio.h>
#define TOTAL_ELEMENTS (sizeof(arry) / sizeof(arry[0]))
int arry[] = {23,34,12,17,204,99,16};
int main()
{
  int d=-1,x;
  if(<= (TOTAL_ELEMENTS-2)

     x=arry[d+1];

      printf("%d\n",x);      
  return 0;
}

sizeof()运算 符返回的值是unsigned int型的,因此,int型的d将被自动被转换为unsigned int型,但是这个转换将导致问题。因为d的初值是-1,int型的-1转换为unsigned int型后是一个最大的数字(ffff)。所以比较的时候就失败了。不会有任何输出。

修改:将sizeof()的运算结果显式转换为int即可。if(<= (int)(TOTAL_ELEMENTS-2)

15,找代码出现的问题。

16,用C语言实现函数

17,用C语言实现函数

18,用C++语言实现类String函数。的4个函数。

这个在面试或笔试的时候常问到或考到。

已知类String的原型为:
class String
{
public:
     String(const char *str = NULL);// 普通构造函数
     String(const String &other);    // 拷贝构造函数
     ~ String(void);    // 析构函数
     String & operate =(const String &other);// 赋值函数
private:
     char *m_data;// 用于保存字符串
}; 
请编写String的上述4个函数。
//普通构造函数
String::String(const char *str)
{
        if(str==NULL)
        {
                m_data = new char[1]; // 得分点:对空字符串自动申请存放结束标志'\0'的//加分点:对m_data加NULL 判断
                *m_data = '\0';
        }    
        else
        {
         int length = strlen(str);
         m_data = new char[length+1]; // 若能加 NULL 判断则更好
         strcpy(m_data, str);
        }
} 
// String的析构函数
String::~String(void)
{
        delete [] m_data; // 或delete m_data;
}
//拷贝构造函数
String::String(const String &other)    // 得分点:输入参数为const型
{     
        int length = strlen(other.m_data);
        m_data = new char[length+1];     //加分点:对m_data加NULL 判断
        strcpy(m_data, other.m_data);    
} 
//赋值函数
String & String::operate =(const String &other) // 得分点:输入参数为const型
{     
        if(this == &other)                    //得分点:检查自赋值
                return *this;   
        delete [] m_data;                //得分点:释放原有的内存资源
        int length = strlen( other.m_data );      
        m_data = new char[length+1];  //加分点:对m_data加NULL 判断
        strcpy( m_data, other.m_data );   
        return *this;             //得分点:返回本对象的引用  

}

剖析:

能够准确无误地编写出String类的构造函数、拷贝构造函数、赋值函数和析构函数的面试者至少已经具备了C++基本功的60%以上!
在这个类中包括了指针类成员变量m_data,当类中包括指针类成员变量时,一定要重载其拷贝构造函数、赋值函数和析构函数,
这既是对C++程序员的基本要求,也是《Effective C++》中特别强调的条款。
仔细学习这个类,特别注意加注释的得分点和加分点的意义,这样就具备了60%以上的C++基本功!

#include<iostream>
using namespace std;

class String
{
  friend ostream& operator<<(ostream& out,const String& str)  //输出操作符重载
  {
   return str.Print(out);
  }
  public:
 String(const char *str = 0);// 普通构造函数
 String(const String &other); // 拷贝构造函数
 ~String(void) { delete [] data_; }// 析构函数
 String& operator=(const String &other);// 赋值函数
 char* data(void) const { return data_; }
  private:
 ostream& Print(ostream& out) const;
 char   *data_;    // 用于保存字符串
};

//赋值操作符首先要注意是不是自己赋给自己,如果是这样的话什么也不做,把自己返回即可。

//其次就是别人赋值给自己,这时首先要自己把原来的值扔到,根据别人的大小开辟一块空间

//准备盛放别人的内容,最后不要忘了返回对自己的引用。

String& String::operator =(const String& other)
{
 if(this!=&other)
 {
  delete [] data_;
  size_t length=strlen(other.data());
  data_=new char[length+1];
  strcpy_s(data_,length+1,other.data());
 }
 return *this;
}

//复制构造函数总是发生在构造阶段,所以此时成员data_还没有空间可以使用,应该先根据别

//人空间的大小开辟好空间,然后在把别人的内容拷贝进来。

String::String(const String &other)
{
 size_t length=strlen(other.data());
 data_=new char[length+1];
 strcpy_s(data_,length+1,other.data());
}

//由于输出操作符通常写成类的友元函数,这样就可以写类似cout<<s;如果不是这样使用起来就会

//很奇怪,比如可能是s.print()之类,无法像cout<<s<<s1<<endl;那样和标准库完美结合,甚至如果

//你写了一个ostream& operator<<(ostream& out,const String& str)忘了加上友元声明,编译器

//会认为你是重载了一元移位操作符<<,而且参数还加多了。

//输出操作符的经典写法就像本文这样,另加一个Print成员函数来完成干活的功能让<<来调用,之所

//以返回ostream& 也是和C++语言内建操作符机制保持一致,这样就可以写cout<<s<<s1<<endl;而不是

//cout<<s;cout<<s1;cout<<endl;

ostream& String::Print(ostream& out) const
{
 out<<data_;
 return out;
}

//此构造函数可以支持隐式类型转换比如你可以这样创建一个String对象 String s("Hello World !");此语句

//就是在调用这个构造函数,另外String s="Hello World !";会被解释成String s=Sting("Hello World !");先

//根据字符数组构造一个临时String对象(此对象在这条语句执行完之后就被析构),并紧接着调用String的赋值

//操作符重载函数

String::String(const char *str) // 6分
{
 if(str==NULL)                          
 {
  data_=new char[1];// 若能加 NULL 判断则更好
  *data_='\0';                      
 }                                        
 else
 {
  size_t length = strlen(str);           
  data_ = new char[length+1]; // 若能加 NULL 判断则更好      
  strcpy_s(data_,length+1, str);                
 }

void main()
{
 char* p="Hello World !";
 String s(p);
 cout<<s<<endl;
 String s1("How are you ?");
 cout<<s1<<endl;
 s1=s;
 cout<<s<<endl<<s1<<endl;
 s=s=s1;
 cout<<s<<endl<<s1<<endl;
}


19,编程。

20,Josephu问题编程。

已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。

例如:n = 9, k = 1, m = 5
【解答】出局人的顺序为5, 1, 7, 4, 3, 6, 9, 2, 8。

int main()//约瑟夫环
{
    int n=9, m=5,k=2;//n是人数(编号1,2,……,x),m是出列号,k是起始人编号
    int j=0, l=0;
    int a[10];
    for (int i=1;i<=9;i++)
    {
        a[i]=1;
    }

    while (l<n) 
    {
        for (int i=1;i<=n;i++) 
        {
            if (a[i]==1) 
            {
                j++;
                if (j==m) 
                {//满足出列号
                    a[i]=0;
                    if (i==n&&k>1) 
                    {
                        cout<<1<<endl;
                    }
                    else
                    {
                        cout<<i+(k-1)<<endl;
                    }
                    j=0;
                    l++;
                }
            }
        }
    }

}

顺便附上一个数学思想的约瑟夫环解法,要求有点不一样。就是一共n个人,查到m的人出圈,求最后圈里的人是几号。

int fun(int n, int m)
{
    int i, r = 0;
    for (i = 2; i <= n; i++)
        r = (r + m) % i;
    return r+1;
}

好巧妙,真简洁,可惜我不理解。






  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值