2020.04.26 鲁大师C++实习笔试题目
本文最后更新于:2020年4月28日 凌晨
昨天在拉勾上投了鲁大师的C++实习岗位,今天下午接到了HR的电话,商量了下晚上七点做笔试。
没有使用在线笔试平台,HR直接发给我的一个word文档。简要记录一下,以下解答为笔试结束后整理~
题目一:符号&的意义
题目:下列几个C语言表达式是否正确?如果正确,写出它们表达的意思:
a&b
a&(&b)
a&&b
a**b
解答:
- 正确。结果为
a
与b
的二进制按位相与; - 不正确。括号内为取址符,取变量
b
的地址;括号外为按位与运算; - 正确。逻辑运算符,当且仅当
a
,b
同时为真时,结果为真; - 正确。前一个为乘法运算,后一个表示指针,即变量
a
乘上指针b
所指向的变量的值。
题目二:内存分配
题目:char a[] = "Hello";
sizeof(a)
是多少?char *b= "Hello";
sizeof(b)
是多少?
解答:
char a[] = "Hello";
sizeof(a)
是6
。五个字符加一个结束符'\0'
;char *b= "Hello";
sizeof(b)
在32位系统下是4
,64位系统下是8
,即sizeof(char*)
的大小。
题目三:宏定义
题目:#ifndef
,#define
,#endif
是做什么用的?构思一个场景用一下。
解答:
宏定义。#define
为定义一个宏;#ifndef
判断一个宏是否已经定义过,避免重复定义;#endif
搭配 #ifndef
使用,结束判断。
场景:可以用于头文件的引用,多文件相互引用时,可能会存在重复引用的情况,这时就可以先判断一个头文件是否已经引用,如果未引用,则通过宏定义引用,否则不再重复引用。
题目四:static
题目:C语言函数前面加static,和C++类的成员函数前面加static,两者的意义有何区别?
解答:
在C和C++中 static
都有扩展生存周期的作用,static
静态变量在其作用范围内仅进行一次初始化操作。
C++中在类的成员函数前面加 static
表示该函数为静态成员函数,这个函数不属于这个类的任何一个实例化对象,而仅属于这个类,并且静态成员函数内部也不能访问该类的非静态成员。
C/C++ 中 static 的用法全局变量与局部变量:https://www.runoob.com/w3cnote/cpp-static-usage.html
题目五:找出程序的问题
题目:这段代码有哪些问题。
char* GetTextA(void)
{
char p[] = "AAAAAAAA";
return p;
}
char* GetTextB(void)
{
char *p = "BBBBBBBB";
return p;
}
void main(void)
{
char *p = NULL;
p = GetTextA();
printf(p);
p = GetTextB();
printf(p);
}
解答:
char* p = "BBBBBBBB";
中"BBBBBBBB"
为const char*
类型的常量,不能用来初始化一个char*
类型的变量。可以使用const_cast<>()
函数去除常量性,也就是可以将该语句更改为:char* p = const_cast("BBBBBBBB");
。- 函数
GetTextB(void)
和GetTextB(void)
中的变量p
为局部变量,作用域为所在的函数内部,函数调用结束后变量p
所占用的内存就会被释放掉,而main()
函数中的指针p
仍指向已释放内存的地址,输出的结果将是无意义的。一个简单的解决办法是,可以将两个函数中的p
声明为static
的,延长其生命周期,直到程序运行结束以后才释放。(参考题目四)
修改后的代码为:
char* GetTextA(void)
{
static char p[] = "AAAAAAAA";
return p;
}
char* GetTextB(void)
{
static char* p = const_cast<char*>("BBBBBBBB");
return p;
}
void main(void)
{
char* p = NULL;
p = GetTextA();
printf(p);
p = GetTextB();
printf(p);
}
题目六:内存泄漏
题目:什么是内存泄漏?
解答:由于疏忽或错误造成程序未能释放已经不再使用的内存。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。(来自维基百科)
题目七:Windows API
题目:描述三个 Windows API。(用途、大致用法)
解答:API Index for desktop Windows applications:https://docs.microsoft.com/en-us/windows/win32/apiindex/api-index-portal
题目八 unsigned long 转字符串
题目:写程序,把 unsigned long
型变量转为字符串。在函数调用上,只允许使用 malloc
这个函数,无需 free,不准调用其它函数。如果不调用任何函数更好。如果使用数组要指出数组大小的设置理由。用注释指出哪个变量是结果即可,无需输出。
解答:
string ultostr(unsigned long n) {
string str = "";
while (n != 0)
{
unsigned long x = n % 10;
str.insert(str.begin(), '0' + x);
n /= 10;
}
return str;//结果
}
题目九:统计字母出现的次数
题目:写程序,输入一个由英文小写字母组成的字符串,字母可重复出现,'0'
结尾,统计每个字母出现的次数。输出格式自定。
解答:
笔试的时候连题目都搞错了,因为前些天刚做过压缩字符串的题目,那个题是把连续相同的多个字符压缩为两个个数加该字符,例如字符串
"aaabbbbcc"
就可以压缩为"3a4b2c"
。但是,这个题目它不一样吖,人都傻了……
'0'
应该也是字符串的一部分,解题的时候我并没有把它作为字符串的一部分。
#include <iostream>
#include <vector>
using namespace std;
int main() {
string str = "";
char c;
while (cin >> c)
{
str += c;
if (c == '0') {//'0'应该也是字符串的一部分
break;
}
}
vector<pair<char, int>> vec;//存储统计信息
for (int i = 0; str[i] != '0'; i++) {
bool exist = false;
for (int j = 0; j < vec.size(); j++) {
if (str[i] == vec[j].first) {
exist = true;
vec[j].second++;
break;
}
}
if (exist == false) {
vec.push_back({ str[i],1 });
}
}
//输出统计结果
for (auto v : vec) {
cout << v.first << v.second << endl;
}
return 0;
}
题目十:字符串查找
题目:完成这个程序。input
是一个由英文小写字母组成的字符串,'0'
结尾。sub_string
是一个由英文小写字母组成的字符串,'0'
结尾。要查找 sub_string
在 input
中第一次出现时的位置(返回这个地址),如果没找到,则返回 NULL
。不准调用任何函数。
char* strstr(char *input, char *sub_string)
{
...
}
解答:
笔试的时候做的这个题直接写的代码,都没来得及调试,实际上也确实写错了,其中找到的几个问题:
'0'
也应该是字符串的一部分;- 对
sub_string
的遍历不应该以NULL
作为结束标志,而是'\0'
;- 二层循环对字符进行遍历,应该更新指针,最初的代码忘了更改指针了。
char* strstr(char* input, char* sub_string)
{
char* ans = new char();//结果
char* s1 = input;
char* s2 = sub_string;
while (s1 != NULL)
{
if (*s1 == *s2) {
ans = &(*s1);
bool find = true;
while (*s2 != '\0')//NULL不是结束标志
{
if (*s1 != *s2) {
find = false;
break;
}
//更改指针指向下一个字符
s1++;
s2++;
}
if (find) {
break;
}
else {
s1 = ans;
s2 = sub_string;
}
}
s1++;
}
return ans;//返回结果
}