3. C/C++笔试面试经典题目三
64. 如何打印出当前源文件的文件名以及源文件的当前行号?
【参考答案】cout << __FILE__ ;
cout<<__LINE__ ;
__FILE__和__LINE__是系统预定义宏,这种宏并不是在某个文件中定义的,而是由编译器定义的。(c也有)
65. 下面两种if语句判断方式。请问哪种写法更好?为什么?
int n;
if (n == 10) // 第一种判断方式
if (10 == n) // 第二种判断方式
【参考答案】这是一个风格问题,第二种方式如果少了个=号,编译时就会报错,减少了出错的可能行,可以检测出是否少了=。
66. 写出运行结果:
void main() {//test1 char str[] = "world"; cout << sizeof(str) << ":"; char *p = str; cout << sizeof(p)<<":"; char i = 10; cout << sizeof(i)<<":"; void *pp = malloc(10); cout << sizeof(pp) << endl; cin.get(); }
【参考答案】6:4:1:4
67. 在不用第三方参数的情况下,交换两个参数的值。
【参考答案】
void main() { int a = 10, b = 20; cout << "a = " << a << "," << "b = " << b << endl; //a=10,b=20 //方法一:使用异或 a = a^b; b = a^b; a = a^b; cout << "a = " << a << "," << "b = " << b << endl; //a=20,b=10 //方法二:使用加减法 a = a + b; b = a - b; a = a - b; cout << "a = " << a << "," << "b = " << b << endl; //a=10,b=20 cin.get(); }
68. 以下代码如果有错,请该正,并写出输出结果。
void main() { int nArrLength(400), i = 546; for (int i = 0; i < 99999999999; i++); cout << nArrLength << endl; cout << i << endl; cin.get(); }
【参考答案】
void main() { int nArrLength(400), i = 546; //主要是考看对C++的基础知识是否了解这里的int nArrLength(400)是对整数的定义, //当然,命名上有问题,这里是故意这样的,但是,最好是变量名改为 ....[还是您自己看着办了] //最好改为int nArrLength = 400,i = 546; for (int i = 0; i < 99999999999; i++); //这里是考对变量越界理解,同时....,所以,999...应该改为 ~((int)0), //也就是整数中0取反考对变量块作用域的理解,这里的i,在循环后就不存在了 cout << nArrLength << endl; //这里输出 400 cout << i << endl; //这里输出 546 ,这里的i并不是for循环中的i cin.get(); }
69. int i = 5, b = 7;
cout << (i+++b) <<endl;
不用调试,请说出,以上代码在gcc编译过后的执行结果!
【参考答案】12
【解析】i++优先
70. 写一个能做左值的函数(方法有很多)。如:
max(x, y) += 2874 + 55;
drwline(x, y)++;
【参考答案】
#include <iostream> using namespace std; int &max(int &x, int &y) { return x > y ? x : y; } void main() { int x = 55, y = 77; max(x, y) += 12 + 13; cout << "x=" << x << ";y=" << y << endl; //x=55,y=102 cin.get(); }
【解析】引用是最标准的做法;返回值明确来说是左值,但是C++会把有内存实体的右值转换成左值,
C语言中怎么写都是不行的。这就是C思维和C++思维。
71. 看程序,写结果。
#include <iostream> using namespace std; class human { public: ~human() { cout << "human over......" << endl; } void Disp() { cout << "human disp......" << endl; } }; class man : public human { public: ~man() { cout << "man over......" << endl; } void Disp() { cout << "man disp......" << endl; } }; int main() { human *p = new man; p->Disp(); //human disp...... delete p; //human over...... cin.get(); return 0; }
【参考答案】human disp……
human over……
【解析】此时没有虚函数,直接会调用human over……
72. 下面的函数实现在一个固定的数上加上一个数,有什么错误,改正 :
int add_n(int n) { static int i = 100; i += n; return i; }
【参考答案】因为static使得 i 的值会保留上次的值,以后的 i 会一直更新。
【解析】static局部变量始终只会初始化一次。
73. 写出打印结果:
unsigned short array[] = { 1, 2, 3, 4, 5, 6, 7 }; int i = 3; *(array + i) =
【参考答案】4
74. 写一个函数计算当参数为n(n很大)时的值 1-2+3-4+5-6+7……+n。
【参考答案】递归实现:
long fn(long n) { if (n <= 0) { printf("error:n must > 0"); exit(1); } if (0 == n % 2) return (n / 2)*(-1); else return (n / 2)*(-1) + n; }
【解析】用循环很好实现,关键是用递归实现。
75. 字符指针、浮点数指针、以及函数指针这三种类型的变量哪个占用的内存最大?为什么?
【参考答案】指针变量也占用内存单元,而且所有指针变量占用内存单元的数量都是相同的。就是说,不管是指向何种对象的指针变量,它们占用内存的字节数都是一样的,并且要足够把程序中所能用到的最大地址表示出来(通常是一个机器字长)。
【解析】任何指针在32位下都占4个字节。
76. 以下三条输出语句分别输出什么?
char str1[] = "abc"; char str2[] = "abc"; const char str3[] = "abc"; const char str4[] = "abc"; const char *str5 = "abc"; const char *str6 = "abc"; cout << boolalpha << (str1 == str2) << endl; //输出什么 cout << boolalpha << (str3 == str4) << endl; //输出什么 cout << boolalpha << (str5 == str6) << endl; //输出什么
【参考答案】分别输出false,false,true。str1和str2都是字符数组,每个都有其自己的存储区,它们的值则是各存储区首地址,不等;
str3和str4同上,只是按const语义,它们所指向的数据区不能修改。
str5和str6并非数组而是字符指针,并不分配存储区,其后的“abc”以常量形式存于静态数据区,而它们自己仅是指向该区首地址的指针,相等。
77. 以下代码有什么问题?
cout << (true ? 1 : "1") << endl;
【参考答案】三元表达式“?:”问号后面的两个操作数必须为同一类型。
78. 以下代码能够编译通过吗,为什么?
unsigned int const size1 = 2; char str1[size1]; unsigned int temp = 0; cin >> temp; unsigned int const size2 = temp; char str2[size2];
【参考答案】str2定义出错,size2非编译器期间常量,而数组定义要求长度必须为编译期常量。
【解析】作为常量要对其赋值,必须要是一个明确的值;不能用变量对其进行初始化,而数组定义要求长度必须为编译期常量。
79. 以下代码中的输出语句输出0吗,为什么?
struct CLS { int m_i; CLS(int i) :m_i(i){} CLS() { CLS(0); } }; CLS obj; cout << obj.m_i << endl;
【参考答案】不能。在默认构造函数内部再调用带参的构造函数属用户行为而非编译器行为,亦即仅执行函数调用,而不会执行其后的初始化表达式。只有在生成对象时,初始化表达式才会随相应的构造函数一起调用。
【解析】构造函数的委托机制(C++03中不行,C++11中可以)。再次调用CLS(0) 时,等价于m_i 没有初始化,所以此处输出一个没有构造的值,如:-858993460。
80. C++中如何写一个死循环。
【参考答案】while(1){}
或者: for(; 1; 😉
81. 下列语句执行后,a、b、c 的值分别是多少?
int a = 5, b = 7, c; c = a+++b;
【参考答案】a=6,b=7,c=12
82. 在排序方法中,关键码比较次数与记录地初始排列无关的是()。
A、Shell排序 B、归并排序 C、直接插入排序 D、选择排序
【参考答案】D
【解析】对于选择排序,即使是有序的也会把所有值挨个遍历一次。
83. 代码
void func() { static int val; ... }
中,变量 val 的内存地址位于()。
A、已初始化数据段 B、未初始化数据段 C、堆 D、栈
【参考答案】A
【解析】static 变量默认会初始化为0,会自动初始化。
84. 一个栈的入栈序列是A,B,C,D,E,则栈的不可能的输出序列是( ) 。
A、EDCBA; B、DECBA; C、DCEAB; D、ABCDE
【参考答案】C
85. 写出判断ABCD四个表达式的是否正确, 若正确, 写出经过表达式中 a的值。
int a = 4;
(A) a += ( a++ );
(B) a += ( ++a );
(C) ( a++ ) += a;
(D) ( ++a ) += ( a++ );
【参考答案】C错误,左侧不是一个有效变量,不能赋值,可改为(++a) += a;改后答案依次为9,10,10,11。
【解析】a++ 是右值,在寄存器里面,不能直接用 ( a++ ) +=
86. 请你谈谈你是如何使用return语句的。
【参考答案】(1)return 语句不可返回指向“栈内存”的“指针”或者“引用” ,因为该内存在函数体结束时被自动销毁。
(2)要搞清楚返回的究竟是“值” 、 “指针”还是“引用” 。
(3)如果函数返回值是一个对象,要考虑 return 语句的效率。(副本机制)
【解析】return 有副本机制,返回值不能取地址。
87. ①return String(s1 + s2); 和 ②String temp(s1 + s2); return temp; 一样吗?
【参考答案】①这是临时对象的语法,表示“创建一个临时对象并返回它” 。
②将发生三件事。首先,temp 对象被创建,同时完成初始化;然后拷贝构造函数把 temp 拷贝到保存返回值的外部存储单元中;最后,temp 在函数结束时被销毁(调用析构函数) 。然而“创建一个临时对象并返回它”的过程是不同的,编译器直接把临时对象创建并初始化在外部存储单元中,省去了拷贝和析构的花费,提高了效率。
【解析】return 时具有副本机制,return 可以返回一个右值。①在寄存器中,②在内存中。
88. 下列程序的运行结果是
#include <iostream> using namespace std; const char *str = "vermeer"; int main() { const char *pstr = str; cout << "The address of pstr is:" << pstr << endl; cin.get(); }
【参考答案】The address of pstr is: vermeer
【解析】
89. 下列程序输出结果是
inline void max_out(int val1, int val2) { cout << (val1 > val2) ? val1 : val2; } int main() { int ix = 10, jx = 20; cout << "The larger of" << ix; cout << "," << jx << "is"; max_out(ix, jx); cout << endl; cin.get(); }
【参考答案】The larger of 10, 20 is 0 ,为什么不是20呢?问题在于输出操作符的优先级高于条件操作符 所以输出 val1和 val2比较结果的 true/false 。
90. int max( int *ia, int sz );
int max( int *, int = 10 );
算函数重载?还是重复声明?
【参考答案】如果在两个函数的参数表中只有缺省实参不同则第二个声明被视为第一个的重复声明 。
91. 请编写一个 C 函数,该函数给出一个字节中被置 1 的位的个数。
【参考答案】
#include <iostream> using namespace std; unsigned int TestAsOne(char log) { int i; unsigned int num = 0, val; for (i = 0; i < 8; i++) { val = log >> i; //移位 val &= 0x01; //与1相与 if (val) num++; } return num; } void main() { char x = 'a'; int count = TestAsOne(x); cout << count << endl; //3 system("pause"); return ; }
【解析】 方法一:位移; 方法二:n & (n-1)。
92. 编写一个函数,函数接收一个字符串,是由十六进制数组成的一组字符串,函数的功能是把接到的这组字符串转换成十进制数字.并将十进制数字返回。
【参考答案】
#include <iostream> using namespace std; bool HexToDec(const char *shex, int &idec) //原来是LPCTSTR shex,此处替换为const char *shex { int i, mid; int len = strlen(shex); if (len > 8) return false; mid = 0; idec = 0; for (i = 0; i < len; i++) { if ( shex[i] >= '0' && shex[i] <= '9' ) mid = shex[i] - '0'; else if ( shex[i] >= 'a' && shex[i] <= 'f' ) mid = shex[i] - 'a' + 10; else if ( shex[i] >= 'A' && shex[i] <= 'F' ) mid = shex[i] - 'A' + 10; else return false; mid <<= ((len - i - 1) << 2); //位移表示变为2的n次方倍 idec = idec + mid; } return true; } void main() { char *res = "fffff"; int des = 0; HexToDec(res, des); cout << des << endl; cin.get(); }
93. 输入一个字符串,将其逆序后输出 。
【参考答案】
#include <iostream> #include <string> #include <algorithm> using namespace std; //方法一: void reverse1(char *str) { char t; //交换的中间变量 for (int i = 0, j = strlen(str) - 1; i < strlen(str) / 2; i++, j--) { t = str[i]; str[i] = str[j]; str[j] = t; } } //方法二: void reverse2(char *str) { char t; //交换的中间变量 int head = 0; //字符数组第一个字符 int tail = strlen(str) - 1; //字符数组最后一个字符 for (; head < tail; head++, tail--) { swap(str[head], str[tail]); } } //方法三:直接调用函数 _strrev() ,注意:strrev()不能对string类型使用 //方法四:直接调用算法中的reverse()函数,需要包含头文件 #include <algorithm> //方法五:使用replace()函数 void main() { char a[50]; memset(a, 0, sizeof(a)); cin.getline(a, 50, '\n'); //reverse1(a); //reverse2(a); //_strrev(a); reverse(a,a+strlen(a)); //此处本应该用迭代器,改为了指针,正常用法如下: //string s = "hello"; //reverse(s.begin(),s.end()); cout << a << endl; cin.get(); }
94. 编写一个算法frequency,统计在一个输入字符串中各个不同字符出现的频度。用适当的测试数据来验证这个算法。
【参考答案】
1 #include <iostream> 2 3 using namespace std; 4 5 void frequency(string &s, char *A, int *C, int &k) //A[]用来存放字符串中出现的各个字符 6 { //C[]用来存放各个字符对应的频次 7 int i, j, len = s.length(); //k用来记录不同字符的个数 8 9 if (!len) //字符串为空串 10 { 11 cout << "The string is empty." << endl; 12 k = 0; 13 return; 14 } 15 else 16 { 17 A[0] = s[0]; //语句s[i]是串的重载操作 18 C[0] = 1; 19 k = 1; 20 for (i = 1; i < len; i++) //初始化C[1~len-1]为0 21 C[i] = 0; 22 for (i = 1; i < len; i++) //检测串中所有字符 23 { 24 j = 0; 25 while ( j < k && A[j] != s[i] ) //检查s[i]是否已在A[]中 26 j++; 27 if (j == k) //s[i]从未检测过 28 { 29 A[k] = s[i]; 30 C[k]++; 31 k++; 32 } 33 else //s[i]已经检测过 34 C[j]++; 35 } 36 } 37 38 } 39 40 void main() 41 { 42 string str = "abbcccddddeeeee"; 43 44 char A[20]; 45 int C[20],k; 46 47 frequency(str, A, C, k); 48 49 cout << "出现的不同字符的个数为:" << k << endl; 50 cout << "出现的 各个字符 以及 各字符出现的次数 依次如下:" << endl; 51 for (int i = 0; i < k; i++) 52 { 53 cout << A[i] <<" "; 54 } 55 cout << endl; 56 for (int i = 0; i < k; i++) 57 { 58 cout << C[i] << " " ; 59 } 60 cout << endl; 61 62 cin.get(); 63 }
95. 假设以数组Q[m]存放循环队列中的元素, 同时以rear和length分别指示环形队列中的队尾位置和队列中所含元素的个数。试给出该循环队列的队空条件和队满条件, 并写出相应的插入(enqueue)和删除(dlqueue)元素的操作。
【参考答案】
#include <iostream> #include <assert.h> using namespace std; template <class Type> class Queue //循环队列的类定义 { public: Queue(int = 10); ~Queue() { delete[] elements; } void EnQueue(Type &item); Type DeQueue(); Type GetFront(); void MakeEmpty() { length = 0; } //置空队列 int IsEmpty() const { return length == 0; } //判队列是否为空 int IsFull() const { return length == maxSize; }//判队列是否为满 private: int rear, length; //队尾指针和队列长度 Type *elements; //存放队列元素的数组 int maxSize; //队列最大可容纳元素个数 }; template <class Type> Queue<Type>::Queue(int sz) :rear(maxSize - 1), length(0), maxSize(sz) //建立一个最大具有maxSize个元素的空队列。 { elements = new Type[maxSize]; //创建队列空间 assert(elements != 0); //断延: 动态存储分配成功与否 } template <class Type> void Queue<Type>::EnQueue(Type &item) { assert(!IsFull()); //判队列是否不满,满则出错处理 length++; //长度加1 rear = (rear + 1) % maxSize; //队尾位置进1 elements[rear] = item; //进队列 } template <class Type> Type Queue<Type>::DeQueue() { assert(!IsEmpty()); //判断队列是否不空,空则出错处理 length--; //队列长度减1 return elements[(rear - length + maxSize) % maxSize]; //返回原队头元素值 } template <class Type> Type Queue<Type>::GetFront() { assert(!IsEmpty()); return elements[(rear - length + maxSize) % maxSize]; //返回原队头元素值 }
96. 已知A[n]为整数数组,试写出实现下列运算的递归算法:
(1) 求数组A中的最大整数。
(2) 求n个整数的和。
(3) 求n个整数的平均值。
【参考答案】
#include <iostream> using namespace std; //数组类声明 class RecurveArray { public: RecurveArray(int MaxSize = 10) : ArraySize(MaxSize), Elements(new int[MaxSize]) {} ~RecurveArray() { delete[] Elements; } void InputArray(); //输入数组的内容 int MaxKey(int n); //求最大值 int Sum(int n); //求数组元素之和 float Average(int n); //求数组元素的平均值 private: int *Elements; //数组指针 int ArraySize; //数组尺寸 int CurrentSize; //当前已有数组元素个数 public : }; //输入数组内容 void RecurveArray::InputArray() { cout << "Input the number of Array:\n"; for (int i = 0; i < ArraySize; i++) cin >> Elements[i]; } //递归求数组元素的最大值 int RecurveArray::MaxKey(int n) { if( 1 == n ) return Elements[0]; int temp = MaxKey(n - 1); if (Elements[n - 1] > temp) return Elements[n - 1]; else return temp; } //递归求数组各元素之和 int RecurveArray::Sum(int n) { if (1 == n) return Elements[0]; else return Elements[n - 1] + Sum(n - 1); } //递归求数组各元素的平均值 float RecurveArray::Average(int n) { if (1 == n) return (float)Elements[0]; else return ( (float)Elements[n - 1] + (n - 1)*Average(n - 1) ) / n; } int main(int argc,char *argv[]) { int size = -1; cout << "No. of the Elements:"; while (size < 1) cin >> size; RecurveArray ra(size); ra.InputArray(); cout << "\nThe max is:" << ra.MaxKey(size) << endl; cout << "\nThe sum is:" << ra.Sum(size) << endl; cout << "\nThe avg is:" << ra.Average(size) << endl; system("pause"); return 0; }
97. 已知f为单链表的表头指针, 链表中存储的都是整型数据,试写出实现下列运算的递归算法:
(1) 求链表中的最大整数。
(2) 求链表的结点个数。
(3) 求所有整数的平均值。
【参考答案】
//RecurveList.h文件 #pragma once #include <iostream> using namespace std; class List; class ListNode //链表结点类 { friend class List; private: int data; //结点数据 ListNode *next; //结点指针 ListNode(const int item) :data(item), next(NULL) {} //构造函数 }; class List //链表类 { private: ListNode *first, *current; int Max(ListNode *f); int Num(ListNode *f); float Avg(ListNode *f); //float Avg(ListNode *f, int &n); public: List() :first(NULL), current(NULL) {} //构造函数 ~List() {} //析构函数 ListNode *NewNode(const int item); //创建链表结点, 其值为item void NewList(const int retvalue); //建立链表, 以输入retvalue结束 void PrintList(first); //输出链表所有结点数据 int GetMax() { return Max(first); } //求链表所有数据的最大值 int GetNum() { return Num(first); } //求链表中数据个数 float GetAvg() { return Avg(first); } //求链表所有数据的平均值 }; //创建新链表结点,其值为item ListNode * List :: NewNode(const int item) { ListNode *newnode = new ListNode(item); return newnode; } //建立链表, 以输入retvalue结束 void List :: NewList(const int retvalue) { first = NULL; int value; ListNode *q; cout << "Input your data:\n"; //输出提示 cin >> value; //输入 while (value != retvalue) //输入有效 { q = NewNode(value); //建立包含value的新结点 if (first == NULL) //空链表时, 新结点成为链表第一个结点 first = current = q; else //非空链表时, 新结点链入链尾 { current->next = q; current = q; } cin >> value; //再输入 } current->next = NULL; //链尾封闭 } //输出链表所有结点数据 void PrintList() { cout << "\nThe List is:\n"; ListNode *p = first; while (p != NULL) { cout << p->data << ' '; p = p->next; } cout << '\n'; } //递归算法 : 求链表中的最大值 int List :: Max(ListNode *f) { if (f->next == NULL) //递归结束条件 return f->data; int temp = Max(f->next); //在当前结点的后继链表中求最大值 if (f->data > temp) return f->data; else return temp; } //递归算法 : 求链表中结点个数 int List :: Num(ListNode *f) { if (f == NULL) //空链表,返回0 return 0; return 1 + Num(f->next); //否则,返回后继链表结点个数加1 } //递归算法 : 求链表中所有元素的平均值 float List :: Avg(ListNode *f, int &n) { if (f->next == NULL) //链表中只有一个结点, 递归结束条件 { n = 1; return (float)(f->data); } else { float Sum = Avg(f->next, n)*n; n++; return (f->data + Sum) / n; } }
//RecurveList.cpp文件 #include <iostream> #include "RecurveList.h" using namespace std; void main() { List test; int finished; cout << "输入链表结束标志数据:"; cin >> finished; test.NewList(finished); test.PrintList(); cout << "\nThe Max is :" << test.GetMax(); cout << "\nThe Num is :" << test.GetNum(); cout << "\nThe Avg is :" << test.GetAvg()<<'\n'; system("pause"); return ; }
98. 字符串的替换操作 replace (String &s, String &t, String &v) 是指:
若t是s的子串,则用串v替换串t在串s中的所有出现;若t不是s的子串,则串s不变。
例如,若串s为“aabbabcbaabaaacbab”,串t为“bab”,串v为“abdc”,则执行replace操作后,
串s中的结果为“aababdccbaabaaacabdc”。试利用字符串的基本运算实现这个替换操作。
【参考答案】
string &string::replace(string &t, string &v) { if ((int id = Find(t)) == -1) //没有找到,当前字符串不改,返回 { cout << "The (replace) operation failed." << endl; return *this; } string temp(ch); //用当前串建立一个空的临时字符串 ch[0] = '\0'; //当前串作为结果串,初始为空 curLen = 0; int j, k = 0, l; //存放结果串的指针 while (id != -1) { for (j = 0; j < id; j++) ch[k++] = temp.ch[j]; curLen += id + v.curLen; //修改结果串连接后的长度 if (curLen <= maxLen) //确定替换串v传送字符数l l = v.curLen; else { l = curLen - maxLen; curLen = maxLen; } for (j = 0; j < l; j++) //连接替换串v到结果串ch后面 ch[k++] = v.ch[j]; if (curLen == maxLen) //字符串超出范围 break; for (j = id + t.curLen; j < temp.curLen; j++) //删改原来的字符串 temp.ch[j - id - t.curLen] = temp.ch[j]; temp.curLen -= (id + t.curLen); id = temp.find(t); return *this; } }
99. 试编写一个求解Josephus(约瑟夫)问题的函数。
用整数序列1, 2, 3, ……, n表示顺序围坐在圆桌周围的人,并采用数组表示作为求解过程中使用的数据结构。
然后使用n = 9, s = 1, m = 5,以及n = 9, s = 1, m = 0,或者n = 9, s = 1, m = 10作为输入数据,检查你的程序的正确性和健壮性。(n:表示总人数,s:表示报名起始位置,m:表示数到m这个人自杀)
【参考答案】
void Josephus(int A[], int n, int s, int m) { int i, j, k, tmp; if (m == 0) { cout << "m=0 是无效的参数!" << endl; return; } for (i = 0; i < n; i++) //初始化,执行n次 A[i] = i + 1; i = s - 1; //报名起始位置 for (k = n; k > 1; i--) //逐个出局,执行n-1次 { if (i == k) i = 0; i = (i + m - 1) % k; //寻找出局位置 if (i != k - 1) //出局者交换到第k-1位置 { tmp = A[i]; for (j = i; j < k - 1; j++) //A[j]后面元素依次往前移动一个位置 A[j] = A[j + 1]; A[k - 1] = tmp; } } for (k = 0; k < n / 2; k++) //全部逆置, 得到出局序列 { tmp = A[k]; A[k] = A[n - k + 1]; A[n - k + 1] = tmp; } }
100. 编写类 String 的构造函数、析构函数和赋值函数已知类 String 的原型为:
class String { public: String(const char *str = NULL); //普通构造函数 String(const String &other); //拷贝构造函数 ~String(void); //析构函数 String & operate = (const String & other); //赋值函数 private: char *m_data; //用于保存字符串 };
请编写 String 的上述 4 个函数。
【参考答案】
//String的析构函数 String::~String(void) { delete[] m_data; //由于 m_data 是内部数据类型,也可以写成 delete m_data; } //String 的普通构造函数 String::String(const char *str) { if (str == NULL) { m_data = new char[1]; //若能加 NULL 判断则更好 *m_data = '\0'; } else { int length = strlen(str); m_data = new char[length + 1]; strcpy(m_data, str); } } //String 的拷贝构造函数 String::String(const String &other) { int length = strlen(other.m_data); m_data = new char[length + 1]; //若能加 NULL 判断则更好 strcpy(m_data, other.m_data); } //String 的赋值函数 String & String::operate = (const String &other) { if (this == &other) return *this; delete[] m_data; int length = strlen(other.m_data); m_data = new char[length + 1]; strcpy(m_data, other.m_data); return *this; }