1.1 在 Linux 系统中,一个函数库通常中是这样存在的:
lrwxrwxrwx 1 root root 23 3月 8 11:54 libminigui.so
-> libminigui-1.6.so. 2.0.0
lrwxrwxrwx 1 root root 23 3月 8 11:54
libminigui-1.6.so.2 -> libminigui-1.6.so. 2.0.0
-rwxr-xr-x 1 root root 1551241 3月 8 11:54
libminigui-1.6.so. 2.0.0
-rw-r--r-- 1 root root 5278658 3月 8 11:54 libminigui.a
-rwxr-xr-x 1 root root 738 3月 8 11:54 libminigui.la
请问,这些文件的名称都有什么具体含义?
答:以上文件是libminigui的链接库文件,*.a是静态库,*.so .sa为共享库。
1.2 在 vim 中,遇到如下的编辑问题,应该怎么操作?
a) 撤消上一个编辑操作。 u
b) 重复上一个编辑操作。 .
c) 还原被撤消的编辑操作。 ^ R(ctrl+R)
d) 多次重复一组编辑操作。
在命令模式下,按‘qabc’其中‘q’开始记录命令,‘abc’为命令的名字;开始你的操作,按‘q’键结束记录;使用@abc回放刚才记录的命令运用。
e) 把一段文字转换为全部大写。 段落的开头按v },再按shift+U
1.3 请看下面的目录属性,并回答后面的问题。
drwxrwsr-x 7 snig team 4096 4月 8 19:34 minigui
a) 这里的 s 属性有何作用?
set-uid位。当程序执行的时候,会改变执行权限,既设置了set-uid位后程序的执行权限变为文件所有者权限。
b) 属性字段后的数字 7 表示什么?
子目录的个数 包含. ..目录。
2.2 请写出下面代码在 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)); // 30
printf("%d/n", sizeof(b)); // 4
printf("%d/n", sizeof(a[3])); // 1
printf("%d/n", sizeof(b+3));1 // 4
printf("%d/n", sizeof(*(b+4)) ); // 1
return 0 ;
}
2.3 请编写一个 C 函数,该函数给出一个字节中被置 1 的位的个数。
int num_1(unsigned char ch)
{
int sum=0;
for(int i=1;i<=8;i++)
sum+=(ch>>i)&0x01?1:0;
return sum;
}
2.4 请编写一个 C 函数,该函数在给定的内存区域搜索给定的字符,并返回该字符所在位置索引怠?
int ch_index(char *str,char ch)
{
char *p = str;
while(*str)
{
if(ch == *str) return str - p;
str++;
}
return npos; //定义npos为“不是合法位置”
}
2.5 请编写一个 C 函数,该函数将一个字符串逆序。
char * strrev (char * string)
{
char *start = string;
char *left = string;
char ch;
while (*string++);
string -= 2; //指向最后一个字符
while (left < string)
{
ch = *left;
*left++ = *string;
*string-- = ch;
}
return(start);
}
2.6 请编写一个 C 函数,该函数将给定的一个字符串转换成整数。
long strtol(const char *nptr, int base)
{
const unsigned char *s = (const unsigned char *) nptr;
unsigned long acc;
unsigned char c;
int neg = 0;
do {
c = *s++;
} while (isspace(c)); //略去空格
if (c == '-') //处理'+','-'号
{
neg = 1;
c = *s++;
}
else if (c == '+')
c = *s++;
if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) //处理基 16
{
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
for (acc = 0; ; c = *s++)
{
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base) break;
acc *= base;
acc += c;
}
if (neg)
acc = -acc;
return acc;
}
2.7 给出演示 2.6 题函数功能的一个简单程序,并请编写对应的 Linux
Makefile 文件。
//test.c 文件
#include <stdio.h>
#include <ctype.h>
int main()
{
int n = strtol("-12345",10);
printf("%d",n);
return 0;
}
#Makefike文件:
test:test.o
gcc –o test test.o
test.o:test.c
gcc –c test.c
或者:
TARGET= test
OBJS= test.o
CC= gcc
CFLAGS= -g -Wall
LIBS= -pthread
OTHE= `allegro-config --libs debug`
${TARGET}:$(OBJS)
$(CC) $^ -g -o $@ $(LIBS) $(OTHE)
3.1 给出 2.3 题的另外一个解法。
使用“查表法”思路。预先定义256个整形的数组,提前完成其索引对应数组值的函数关系,稍后程序中使用该数组,实现如下:
int main()
{
unsigned char i;
int y[256];
memset(y,0,256); //局部变量必须清零
for(i=0;i<256;i++)
y[i] = num_1(i); //num_1()函数是2.3中已经实现的
int n = y[0x45]; //使用y[ ],输出为:n=3
return 0;
}
3.2 请编写一个 C 函数,该函数将给定的整数转换成字符串。
void xtoa (unsigned long val,char *buf,unsigned radix,int is_neg)
{
char *p; /* pointer to traverse string */
char *firstdig; /* pointer to first digit */
char temp; /* temp char */
unsigned digval; /* value of digit */
p = buf;
if (is_neg) {
/* negative, so output '-' and negate */
*p++ = '-';
val = (unsigned long)(-(long)val);
}
firstdig = p; /* save pointer to first digit */
do {
digval = (unsigned) (val % radix);
val /= radix; /* get next digit */
/* convert to ascii and store */
if (digval > 9)
*p++ = (char) (digval - 10 + 'a'); /* a letter */
else
*p++ = (char) (digval + '0'); /* a digit */
} while (val > 0);
/* We now have the digit of the number in the buffer, but in reverse
order. Thus we reverse them now. */
*p-- = '/0'; /* terminate string; p points to last digit */
do {
temp = *p;
*p = *firstdig;
*firstdig = temp; /* swap *p and *firstdig */
--p;
++firstdig; /* advance to next two digits */
} while (firstdig < p); /* repeat until halfway */
}
3.3 请编写一个 C函数,该函数在一个字符串中找到可能的最长的子字符串,且该字符串是由同一字符组成的。
char *strstr (const char * str1,const char * str2)
{
char *cp = (char *) str1;
char *s1, *s2;
if ( !*str2 )
return((char *)str1);
while (*cp)
{
s1 = cp;
s2 = (char *) str2;
while ( *s1 && *s2 && !(*s1-*s2) )
s1++, s2++;
if (!*s2)
return(cp);
cp++;
}
return(NULL);
}
3.4 我们需要编写一个图形相关的应用程序,需要处理大量几何形状 (Shape)
信息,这些形状有
矩形 (Rectangle),正方形 (Square),圆形 (Circle)
等,应用程序需要计算这些几何形状
的面积,并且可能需要在某个设备上进行绘制这些形状
(可在标准输出上打印信息的方式做为示意)。
a) 请用面向对象的方法对以上需求进行设计,编写可能需要的类。
b)
请给出实现以上应用功能的示例性代码,从某处获取图形信息,并且进行计算和绘制。
c) 如果你的 Square 类继承自 Rectangle
类,请给出理由,如果不是,请给出理由,并请比较
两种方式的优劣。
a,b)
#include <iostream.h>
//形状类
/////////////////////////////////////////////////////////
class Shape
{
public:
Shape(){}
virtual double area()=0; //纯虚函数
virtual void draw()=0;
};
//矩形类
////////////////////////////////////////////////////////
class Rect:public Shape
{
public:
Rect(){}
Rect(int a,int b){this->a = a;this->b = b;}
double area(){ return a*b; }
void draw(){cout<<"矩形:"<<area()<<endl;}
private:
int a;
int b;
};
//正方形类
////////////////////////////////////////////////////////
class Squre:public Rect
{
public:
Squre(int x):a(x){}
double area() { return a*a;}
void draw(){cout<<"正方形:"<<area()<<endl;}
private:
int a;
};
//圆形类
////////////////////////////////////////////////////////
class Circle:public Shape
{
public:
Circle(int r){this->r = r;}
double area() { return (3.14*r*r);}
void draw(){cout<<"圆形:"<<area()<<endl;}
private:
int r;
};
void main()
{
Shape *ps = NULL;
Circle c(3);
Rect r(4,5);
ps=&c;
ps->draw(); //圆形
ps=&r;
ps->draw(); //矩形
ps = new Squre(3);
ps->draw(); //正方形
delete ps;
}
c)上述代码中,“正方形”类继承于“矩形”类,按该题意,理解为:正方形类“是一个”矩形类特殊情况较为合适,参考《EffectiveC++》中条款35;这样带来的问题是:涉及更多的虚表使用开销,程序执行效率上的下降,参考《More Effective C++》条款 M24:理解虚拟函数、多继承、虚基类和RTTI所需的代价。