牛客网刷题:C/C++工程师能力评估(共20题)

本文探讨了C++中的虚函数和函数重载的概念,解释了虚函数的作用和实现原理,同时分析了内存管理中动态分配数组的用法,强调了防止内存越界的重要性。此外,还涉及了C++中的枚举类型、类型转换和函数参数传递的细节,以及类的内存布局和函数重载、重写的规则。
摘要由CSDN通过智能技术生成

1

image-20210222195428481

测试代码:

#include <iostream>

int main() {

    std::cout << "int *p1 = new int[10]; \n";
    int *p1 = new int[10];
    for(int i=0;i<10;i++)
    {
        std::cout << p1[i] << "\t";
    }

    std::cout << "\nint *p1 = new int[10]; \n";
    int *p2 = new int[10]();
    for(int i=0;i<10;i++)
    {
        std::cout << p2[i] << "\t";
    }

    return 0;
}

image-20210222195230490

2

image-20210222195416133

测试代码:

#include <iostream>
#include <ctime>

using namespace std;

void knuth(int n, int m)
{
    srand((unsigned int)time(0));
    cout << "rand()产生随机数范围为0到"<< RAND_MAX;
    for (int i = 0; i < n; i++) {
        if (rand()%(n-i)<=m) {
            cout << i << endl;
            m--;
        }
    }
}

int main() {

    knuth(10000,1);

    return 0;
}

img

3

image-20210222202259417

测试代码:

#include <iostream>

using namespace std;

void prim(int m, int n)
{
    if (m >= n)
    {
        while (m%n) n++;
        m/=n;
        prim(m, n);
        cout << n << endl;
    }
}

int main() {
    prim(10,2);
    return 0;
}

image-20210222202321391

4

image-20210222202434458

测试代码:

#include <iostream>

using namespace std;

void fun()
{
    enum string{
        x1,
        x2,
        x3=10,
        x4,
        x5,
    } x;

    cout << "x=" << x;
}


int main() {
    fun();
    return 0;
}

image-20210222202820517

5

image-20210222202908450

解析:

{ char每次移动1个字节;short移动2个字节 ;int , long ,float移动4个字节 ;double移动8个字节}

6

image-20210222204226505

解析:

这题的正确答案应该是32位系统是4 64位系统是8,数组作为函数的参数是会退化为函数指针的,想想看,数组作为函数参数的时候经常是需要传递数组大小的。

7 下面关于虚函数和函数重载的叙述不正确的是(A)

image-20210222204335019

解释:

虚函数也是类的成员函数,A说法是不正确的;

8 处理a.html文件时,以下哪行伪代码可能导致内存越界或者抛出异常(B)

         int totalBlank = 0;
         int blankNum = 0;
         int taglen = page.taglst.size();
A       for(int i = 1; i < taglen-1; ++i)
        {
                 //check blank
B             while(page.taglst[i] == "<br>" && i < taglen)
               {
C                       ++totalBlank;
D                       ++i;
               }
E             if(totalBlank > 10)
F                      blankNum += totalBlank;
G             totalBlank = 0;
        }

注意:以上代码中taglen是html文件中存在元素的个数,a.html中taglen的值是15,page.taglst[i]取的是a.html中的元素,例如page.taglst[1]的值是
a.html的文件如下:

<html>
<title>test</title>
<body>
<div>aaaaaaa</div>
</body>
</html>
<br>
<br>
<br>
<br>
<br>

9

image-20210222204749499

解释:

  1. str是复合类型数组char[6],维度6是其类型的一部分,sizeof取其 维度*sizeof(char),故为6;

  2. strlen 求c类型string 的长度,不含尾部的’\0’,故为5;

  3. p只是个指针,32位机上为4;

  4. c++中不允许隐式的数组拷贝,所以Func的参数会被隐式地转为char*,故为4;

    note:若Func的原型为void Func(char (&str_arg) [6])(若不为6则调用出错),则结果为6.

image-20210222205017934

10

image-20210222205122278

解释:

该题的关键是要认清楚强制类型转换后指针的类型。

p的类型为char *,p++后p指向str数组的第2个元素即字母“l”的位置。

p1的类型为int *,p1++后p1指向的位置增加4个字节,指向str数组中的第6个元素即字母“t”的位置。

因此最后p的内容为“to test something”。

11

image-20210222205334908

解释:

这道题主要考察的知识点是 :全局变量,静态局部变量,局部变量空间的堆分配和栈分配

其中全局变量和静态局部变量时从 静态存储区中划分的空间,

二者的区别在于作用域的不同,全局变量作用域大于静态局部变量(只用于声明它的函数中),

而之所以是先释放 D 在释放 C的原因是, 程序中首先调用的是 C的构造函数,然后调用的是 D 的构造函数,析构函数的调用与构造函数的调用顺序刚好相反。

局部变量A 是通过 new 从系统的堆空间中分配的,程序运行结束之后,系统是不会自动回收分配给它的空间的,需要程序员手动调用 delete 来释放。

局部变量 B 对象的空间来自于系统的栈空间,在该方法执行结束就会由系统自动通过调用析构方法将其空间释放。

之所以是 先 A 后 B 是因为,B 是在函数执行到 结尾 “}” 的时候才调用析构函数, 而语句 delete a ; 位于函数结尾 “}” 之前。

12

image-20210222205606238

解释:

考察点:c++ 类的内存布局。

上精华图:一张图说明类中成员变量,成员函数,静态变量与函数的空间位置。

image-20210222205719566

13

image-20210222205811638

解释:

方法重载的返回值的类型可以不同,因为判断方法重载的方法主要是根据方法的参数不同来判定;

方法重写的返回值类型需要相同,重写就是子类继承了父类的方法,并在此方法上重写属于自己的特征,既然是继承过来的,那么它的返回值类型就必须要相同

方法重载(overload):

1.必须是同一个类

2方法名(也可以叫函数)一样

3参数类型不一样或参数数量不一样

**方法的重写(override)**两同两小一大原则:

方法名相同,参数类型相同

子类返回类型小于等于父类方法返回类型,

子类抛出异常小于等于父类方法抛出异常,

子类访问权限大于等于父类方法访问权限。

14

image-20210222210022351

#include <iostream>
#include <cstring>

using namespace std;
#define M 5
#define N 20
int fun(char(* ss)[N], int *n)
{
    int i, k = 0, len = N;
    for (i = 0; i < M; i++)
    {
        len = strlen(ss[i]);
        
        // 把第一个字符串长度赋值给*n
        if (i == 0)
            *n = len;
        
        // 如果新来的len比*n小,则重新赋值*n
        // 并找出下标i,复制给k
        if (len < * n)
        {
            *n = len;
            k = i;
        }
    }
    return k;
}

int main() {
    char ss[M][N] = {"shanghai", "guangzhou", "beijing", "tianjing", "chongqing"};
    int n, k, i;
    printf("\nThe originalb stringsare:\n");
    for (i = 0; i < M; i++)
        puts(ss[i]);
    k = fun(ss, &n);
    printf("\nThe length of shortest string is: % d\n", n);
    printf("\nThe shortest string is: % s\n", ss[k]);

    return 0;
}

解释:

puts() 就是输出

15 写出下面程序的输出结果

# include <iostream>

class A
{
public:
    void FuncA()
    {
        printf( "FuncA called\n" );
    }
    virtual void FuncB()
    {
        printf( "FuncB called\n" );
    }
};
class B : public A
{
public:
    void FuncA()
    {
        A::FuncA();
        printf( "FuncAB called\n" );
    }
    virtual void FuncB()
    {
        printf( "FuncBB called\n" );
    }
};

int main()
{
    B	b;
    A	*pa;
    pa = &b;
    A *pa2 = new A;
    pa->FuncA();	// pa=&b动态绑定但是FuncA不是虚函数,所以FuncA called
    pa->FuncB();	// FuncB是虚函数所以调用B中FuncB,FuncBB called  
    pa2->FuncA();	// pa2是指向A,不涉及虚函数,调用的都是A中函数,所以FuncA called 
    pa2->FuncB();	// FuncB called
    delete pa2;
}

程序云型结果:

image-20210222212803740

16

In the main() function, after ModifyString(text) is called, what’s the value of ‘text’?

int FindSubString( char* pch )
{
    int   count  = 0;
    char  * p1   = pch;
    while ( *p1 != '\0' )
    {    
        if ( *p1 == p1[1] - 1 )
        {
            p1++;
            count++;
        }else  {
            break;
        }
    }
    
    int count2 = count;
    
    while ( *p1 != '\0' )
    {
        if ( *p1 == p1[1] + 1 )
        {
            p1++;
            count2--;
        }else  {
            break;
        }
    }
    if ( count2 == 0 )
        return(count);
    return(0);
}
void ModifyString( char* pText )
{
    char  * p1   = pText;
    char  * p2   = p1;
    while ( *p1 != '\0' )
    {
        int count = FindSubString( p1 );
        if ( count > 0 )
        {
            *p2++ = *p1;
            sprintf( p2, "%i", count );
            while ( *p2 != '\0' )
            {
                p2++;
            }
            p1 += count + count + 1;
        }else  {
            *p2++ = *p1++;
        }
    }
}
void main( void )
{
    char text[32] = "XYBCDCBABABA";
    ModifyString( text );
    printf( text );
}  

解释:

有点难,有时间回来再看

image-20210222213659600

17

image-20210222213914196

解释:

难啊,回来再看

image-20210222213928690

18

image-20210222214610699

解释:

auto int 表示的是局部变量,在我们声明局部变量,或者函数参数,可以加上这个关键字,表明是分配在堆栈中
本程序中的变量b声明为static静态全局变量,所以它的作用域是全局作用域,每次调用sum函数都会累加2

image-20210222214711907

19

#include<iostream>
using namespace std;
class MyClass
{
public:
    MyClass(int i = 0)
    {
        cout << i;
    }
    MyClass(const MyClass &x)
    {
        cout << 2;
    }
    MyClass &operator=(const MyClass &x)
    {
        cout << 3;
        return *this;
    }
    ~MyClass()
    {
        cout << 4;
    }
};
int main()
{
    MyClass obj1(1), obj2(2);
    MyClass obj3 = obj1;
    return 0;
}

运行时的输出结果是(C)

image-20210222214817756

解析:

C D 辨析:

关键是区分 浅/深拷贝操作 和 赋值操作:

没有重载=之前:

A a ;

A b;

a = b;

这里是赋值操作。

A a;

A b = a;

这里是浅拷贝操作。

重载 = 之后:

A a ;

A b;

a = b;

这里是深拷贝操作(当然这道题直接返回了,通常我们重载赋值运算符进行深拷贝操作)。

A a;

A b = a;

这里还是浅拷贝操作。

所以 MyClass obj3 = obj1; 调用的是拷贝构造函数。

如果写成 MyClass obj3; obj3 = obj1; 输出的结果就是 1203444

20

image-20210222215257651

image-20210222215308033

解释:

函数char *myString()中没有使用new或者malloc分配内存,所有buffer数组的内存区域在栈区

随着char *myString()的结束,栈区内存释放,字符数组也就不存在了,所以会产生野指针,输出结果未知

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超级D洋葱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值