一些面试题
1、完成字符串拷贝可以使用 sprintf、strcpy 及 memcpy 函数,请问这些函数
有什么区别,你喜欢使用哪个,为什么?
答:
说明:
sprintf是用在文本显示,但是该函数的实现过于复杂,容易出现内存错误非常危险;
strcpy即标准字符串拷贝函数,遇到'\0'就结束拷贝,如果src比dst大,将出现缓冲区溢出问题;
memcpy用来做内存拷贝,可以用来从一个源地址,拷贝任何数据类型的对象到目标地址;
这三个函数都是比较危险的,所以需要慎重使用。
分析:
(1)对于strcpy,有时候可以使用strncpy函数替代。使用strncpy函数,如果src比dst大,则该函数不
会抛出一个错误;当达到最大尺寸时,它只是停止复制字符。可以避免潜在的缓冲区溢出的问题。
(2)对于sprintf可以使用snprintf来替代,可以避免缓冲区溢出。
(3)memcpy必须保证缓冲区大小保持一致,否则将出现缓冲区溢出。
结论:
通常对于完成字符串拷贝,我通常使用strcpy,因为这是标准C的字符串类型的拷贝函数。对于常量的字
符串拷贝使用strcpy是安全的,有时候可以使用strncpy减少代码的潜在安全问题。
---------------------------------------------
2、变量的声明和定义有什么区别?
答:
变量声明只是给编译器一个提示,和运行环境无关;而变量定义是具体了分配内存空间。
比如:
extern int a; //变量声明
int b; //变量定义
---------------------------------------------
3、请写出下面代码在 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 ;
}
答:
a是一个有30个元素的字符型数组;b是一个字符串指针;a[3]是字符型;b+3是指针;*(b+4)是字符型。
因此输出:
30、2、1、2、1
---------------------------------------------
4、请完成以下题目。注意,请勿直接调用 ANSI C 函数库中的函数实现。
a)请编写一个 C 函数,该函数给出一个字节中被置 1 的位的个数,并请
给出该题的至少一个不同解法。
b)请编写一个 C 函数,该函数将给定的一个字符串转换成整数。
c)请编写一个 C 函数,该函数将给定的一个整数转换成字符串。
d)请编写一个 C 函数,该函数将一个字符串逆序。
e)请编写一个 C 函数,该函数在给定的内存区域搜索给定的字符,并返回
该字符所在位置索引值。
f)请编写一个 C 函数,该函数在一个字符串中找到可能的最长的子字符串,
该字符串是由同一字符组成的。
5、给出演示上述函数功能的一个简单程序,并请编写对应的 Makefile 文件
答:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int A(unsigned char a_char)
{
int cnt = 0;
for (char b = 0x80; a_char; a_char <<= 1) {
if ( a_char >= b )
++cnt;
}
return cnt;
}
int A_other(unsigned char a_char)
{
int cnt = 0;
//a char has 8 bits
for (int i = 0; i < 8; ++i){
cnt += (a_char & 0x01);
a_char >>= 1;
}
return cnt;
}
long B(char* str)
{
long aInt = 0;
long step = 1;
for (int i = strlen(str)-1; i >= 0; --i){
if (str[i] < '0' || str[i] > '9')
return -1;
aInt += (str[i] - '0') * step;
step *= 10;
}
return aInt;
}
int C(long aInt, char* str)
{
int i;
for (i = 0; aInt; aInt /= 10, ++i){
str[i] = (aInt % 10) + '0';
}
str[i] = '\0';
return 0;
}
int D(char *str)
{
int i;
int j = strlen(str) - 1;
char tmp;
for (i = 0; i < j; ++i, --j){
tmp = str[i];
str[i] = str[j];
str[j] = tmp;
}
return 0;
}
int E(char *start, char *end, char **p, const char target)
{
for (*p = start; *p < end; ++(*p)){
if (**p == target){
return 0;
}
}
*p = NULL;
return 1;
}
int F(char *src, char a)
{
int cnt, index;
char *p;
cnt = index = 0;
for (p = src; *p; ++p){
if (*p == a)
++cnt;
else {
if (index < cnt){
index = cnt;
}
cnt = 0;
}
}
return index;
}
int main(void)
{
char t = 0x8f;
printf("%d\n", A(t));
printf("%d\n", A_other(t));
printf("%ld\n", B("54387"));
char* str;
str = (char *) malloc (4 * sizeof(char));
C(1222345, str);
printf("%s\n", str);
D(str);
printf("%s\n", str);
char *p;
E(str, str+10, &p, '4');
if (p)
printf("%c\n", *p);
printf("%d\n", F(str, '2'));
if (str){
free(str);
str = NULL;
}
return 0;
}
---------------------------------------------
Makefie:
6、我们需要编写一个图形相关的应用程序,需要处理大量图形(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);
}