1. 类中的构造函数和析构函数可以重载吗?说明原因。
构造函数可以,因为可以改变参数个数和类型,符合函数重载的要求;
析构函数不可以,因为参数只有一个固定类型的this,故不可能重载;
2. 分析下面程序的运行结果。
class A {
int a;
public:
A(int a): a(a) { printf("A%d",a); }
A(): a(0) { printf("A%d",a); }
~A() { printf("~A%d",a); }
} a(1);
class B {
int b;
A a1,a2;
public:
B(int b): a1(2),b(b) { printf("B%d",b); }
~B() { printf("~B%d",b); }
} b(9);
int main() { }
输出:A1A2A0B9~B9~A0~A2~A1
3. 下面的类将N进制整数字符串s转换为M进制的字符串,请完成各个成员函数。测试程序为:
int main() { NumString s("A4",16); printf("%s %s", s.toString(10), s.toString(2)); }
class NumString {
const char *s; //s[]为N进制整数字符串(字母都是大写),如"9AB6"(N=16)
const int N; //2 <= N <= 16
int decNum; //在构造函数中,将s[]转换为10进制数保存到该变量
public:
NumString(const char *s, int N=10); //构造函数, s[]是N进制整数字符串,含有大小写字母
~NumString( ); //析构函数
char *toString(int M); //将s[]中的N进制字符串转换为M进制字符串,返回M进制字符串的首地址
private:
void toNum( ); //将s[]中的N进制整数字符串转换为10进制数并保存到decNum
};
解答:
#include <cmath>
#include <cstdio>
class NumString {
const char* s; // s[]为N进制整数字符串(字母都是大写),如"9AB6"(N=16)
const int N; // 2 <= N <= 16
int decNum; // 在构造函数中,将s[]转换为10进制数保存到该变量
public:
NumString(const char* s, int N = 10); // 构造函数, s[]是N进制整数字符串,含有大小写字母
~NumString(); // 析构函数
char* toString(int M); // 将s[]中的N进制字符串转换为M进制字符串,返回M进制字符串的首地址
private:
void toNum(); // 将s[]中的N进制整数字符串转换为10进制数并保存到decNum
};
NumString::NumString(const char* s, int N) : s(s), N(N) {
toNum();
}
NumString::~NumString() {
}
char* NumString::toString(int M) {
int maxLen =(int) (log(decNum) / log(M)) + 2;
char* result = new char[maxLen];
int quot = decNum;
int i = 0;
while (quot > 0) {
int remainder = quot % M;
result[i++] = (remainder < 10) ? remainder + '0' : remainder - 10 + 'A';
quot /= M;
}
if (i == 0) {
result[i++] = '0';
}
for (int j = 0; j < i / 2; j++) {
char tmp = result[j];
result[j] = result[i - j - 1];
result[i - j - 1] = tmp;
}
result[i] = '\0';
return result;
}
void NumString::toNum() {
decNum = 0;
int i = 0;
//printf("%s\n", s);
//printf("%d\n", N);
while (s[i]) {
int digit = 0;
if (s[i] >= '0' && s[i] <= '9') {
digit = s[i] - '0';
}
else if (s[i] >= 'A' && s[i] <= 'F') {
digit = s[i] - 'A' + 10;
}
else if (s[i] >= 'a' && s[i] <= 'f') {
digit = s[i] - 'a' + 10;
}
decNum = decNum * N + digit;
//printf("%c %d %d\n", s[i], digit, decNum);
i++;
}
}
int main() {
NumString s("A4", 16);
printf("%s %s", s.toString(10), s.toString(2));
return 0;
}
4. 集合类的头文件set.h如下,请定义其中的函数成员。
class SET {
int *set; //set用于存放集合元素
int card; //card为能够存放的元素个数
int used; //used为已经存放的元素个数
public:
SET(int card); //card为能够存放的元素个数
~SET( );
int size( ); //返回集合已经存放的元素个数
int insert(int v); //插入v成功时返回1,否则返回0
int remove(int v); //删除v成功时返回1,否则返回0
int has(int v); //元素v存在时返回1,否则返回0
};
解答:
#include<cstdio>
class SET {
int* set; //set用于存放集合元素
int card; //card为能够存放的元素个数
int used; //used为已经存放的元素个数
public:
SET(int card); //card为能够存放的元素个数
~SET();
int size(); //返回集合已经存放的元素个数
int insert(int v); //插入v成功时返回1,否则返回0
int remove(int v); //删除v成功时返回1,否则返回0
int has(int v); //元素v存在时返回1,否则返回0
//测试
void printset();
};
SET::SET(int card) :card(card),used(0) {
set = new int[card];
}
SET::~SET() {
delete []set;
}
int SET::size() {
return used;
}
int SET::insert(int v) {
if (used == card) {
return 0;
}
if (has(v)) {
return 0;
}
set[used++] = v;
return 1;
}
int SET::remove(int v) {
if(used == 0) return 0;
for (int i = 0; i < used; i++) {
if (set[i] == v) {
set[i] = set[used - 1];
used--;
return 1;
}
}
return 0;
}
int SET::has(int v) {
for (int i = 0; i < used; i++) {
if (set[i] == v) {
return 1;
}
}
return 0;
}
void SET::printset() {
printf("{");
for (int i = 0; i < used - 1; i++) {
printf("%d ", set[i]);
}
printf("%d", set[used - 1 ]);
printf("}\n");
}
int main() {
SET mySet(3);
mySet.insert(1);
mySet.printset();
mySet.insert(1);
mySet.printset();
mySet.insert(2);
mySet.printset();
mySet.insert(3);
mySet.printset();
mySet.insert(4);
mySet.printset();
printf("%d \n", mySet.has(3));
}
5. 线性表通常提供元素查找、插入和删除等功能。以下线性表是一个整型线性表,表元素存放在动态申请的内存中,请编程定义整型线性表的函数成员。
class INTLIST {
int *list; //动态申请的内存的指针
int size; //线性表能够存放的元素个数
int used; //线性表已经存放的元素个数
public:
INTLIST(int s); //s为线性表能够存放的元素个数
int insert(int v); //插入元素v成功时返回1,否则返回0
int remove(int v); //删除元素v成功时返回1,否则返回0
int find(int v); //查找元素v成功时返回1,否则返回0
int get(int k); //取表的第k个元素的值作为返回值
~INTLIST( );
};
解答:
#include<cstdio>
class INTLIST {
int* list; //动态申请的内存的指针
int size; //线性表能够存放的元素个数
int used; //线性表已经存放的元素个数
public:
INTLIST(int s); //s为线性表能够存放的元素个数
int insert(int v); //插入元素v成功时返回1,否则返回0
int remove(int v); //删除元素v成功时返回1,否则返回0
int find(int v); //查找元素v成功时返回1,否则返回0
int get(int k); //取表的第k个元素的值作为返回值
void printlist();
~INTLIST();
};
INTLIST::INTLIST(int s) : size(s),used(0){
list = new int [size];
}
INTLIST::~INTLIST() {
delete [] list;
}
int INTLIST::insert(int v) {
if (used == size) {
return 0;
}
list[used++] = v;
return 1;
}
int INTLIST::remove(int v) {
for (int i = 0; i < used; i++) {
if (list[i] == v) {
for (int j = i; j < used - 1; j++) {
list[j] = list[j + 1];
}
used--;
return 1;
}
}
return 0;
}
int INTLIST::find(int v) {
for (int i = 0; i < used; i++) {
if (list[i] == v) {
return 1;
}
}
return 0;
}
int INTLIST::get(int k) {
if (k - 1 >= used || k - 1 < 0) {
printf("wrong index\n");
return -1;
}
return list[k - 1];
}
void INTLIST::printlist() {
for (int i = 0; i < used - 1; i++) {
printf("%d ", list[i]);
}
printf("%d\n", list[used - 1]);
}
int main() {
INTLIST mylist(4);
mylist.insert(1);
mylist.insert(2);
mylist.insert(1);
mylist.insert(3);
mylist.printlist();
printf("at 2 is %d\n", mylist.get(2));
mylist.remove(3);
mylist.printlist();
return 0;
}
6. 下面是二叉树类的定义,请完成各个成员函数。
class TREE {
int item; //节点的值
TREE *left, *right; //左、右子树
public:
TREE(int item); //构造树:item为根节点、左右子树为null
TREE(int item, TREE *left, TREE *right); //构造树:item为根节点、左右子树为left、right
~TREE( );
int getNodeNum( ); //返回节点总数
int getNodes(int items[ ]); //将所有的节点的值保存到items[ ]中
};
解答:
#include<cstdio>
class TREE {
int item; //节点的值
TREE* left, * right; //左、右子树
public:
TREE(int item); //构造树:item为根节点、左右子树为null
TREE(int item, TREE* left, TREE* right); //构造树:item为根节点、左右子树为left、right
~TREE();
int getNodeNum(); //返回节点总数
int getNodeshelper(int items[], int index);
int getNodes(int items[]); //将所有的节点的值保存到items[ ]中
};
TREE::TREE(int item) :item(item) {
left = nullptr;
right = nullptr;
}
TREE::TREE(int item, TREE* left, TREE* right) :item(item), left(left),right(right){
}
TREE::~TREE() {
delete left;
delete right;
}
int TREE::getNodeNum() {
int nodenum = 1;
if (left != nullptr) {
nodenum += left->getNodeNum();
}
if (right != nullptr) {
nodenum += right->getNodeNum();
}
return nodenum ;
}
int TREE::getNodes(int items[]) {
getNodeshelper(items, 0);
return 1;
}
int TREE::getNodeshelper(int items[], int index) {
items[index++] = item;
if (left != nullptr) {
index = left->getNodeshelper(items, index);
}
if (right != nullptr) {
index = right->getNodeshelper(items, index);
}
return index;
}
int main() {
TREE* leaf1 = new TREE(12);
TREE* leaf2 = new TREE(81);
TREE* leaf3 = new TREE(92);
TREE* leaf4 = new TREE(66);
TREE* node1 = new TREE(1, leaf1, leaf2);
TREE* node2 = new TREE(2, leaf3, leaf4);
TREE* root = new TREE(4, node1, node2);
int nodeCount = root->getNodeNum();
printf("nodenum : %d\n", nodeCount);
int *items = new int [nodeCount];
root->getNodes(items);
printf("Nodes: \n");
for (int i = 0; i < nodeCount; i++) {
printf("%d ", items[i]);
}
delete root;
return 0;
}