欢迎c++爱好者一起探讨一下微软公司最近的一道笔试题,应该能有很多收获.

duduhaha 2005-10-21 02:07:25
这是微软的原题.
Implement a string class in C++ with basic functionality like comparison, concatenation, input and output. Please also provide some test cases and using scenarios (sample code of using this class).
我是在vc6.0下写的,写的还不够完善,但大体的功能已经写出来了,有的地方有些图省事用了<cstring>中的库函数.
遇到的问题挺奇怪,经调试应该是析构函数的问题.就是如果调用+=运算符(比如说b += a;),出了主函数作用域对b进行析构时,就会出现警告(在debug模式下),结果能出来,也没错.在release模式下久能很好地运行没有问题.不知道为啥.希望高手指点一下.
等会我到linux下编译试试.

源程序如下:

String.h:

#ifndef STRING_H
#define STRING_H

#include <iostream>
using namespace std;

class String{
public:
String();
String(int n,char c);
String(const char* source);
String(const String& s);
//String& operator=(char* s);
String& operator=(const String& s);
~String();

char& operator[](int i){return a[i];}
const char& operator[](int i) const {return a[i];}//对常量的索引.
String& operator+=(const String& s);
int length();

friend istream& operator>>(istream& is, String& s);//搞清为什么将>>设置为友元函数的原因.
//friend bool operator< (const String& left,const String& right);
friend bool operator> (const String& left, const String& right);//下面三个运算符都没必要设成友元函数,这里是为了简单.
friend bool operator== (const String& left, const String& right);
friend bool operator!= (const String& left, const String& right);
private:
char* a;
int size;
};

#endif


String.cpp:


#include "String.h"
#include <cstring>
#include <cstdlib>

String::String(){
a = new char[1];
a[0] = '\0';
size = 0;
}

String::String(int n,char c){
a = new char[n + 1];
memset(a,c,n);
a[n] = '\0';
size = n;
}

String::String(const char* source){
if(source == NULL){
a = new char[1];
a[0] = '\0';
size = 0;
}
else
{ size = strlen(source);
a = new char[size + 1];
strcpy(a,source);
}
}

String::String(const String& s){
size = strlen(s.a);//可以访问私有变量.
a = new char[size + 1];
//if(a == NULL)
strcpy(a,s.a);
}



String& String::operator=(const String& s){
if(this == &s)
return *this;
else
{
delete[] a;
size = strlen(s.a);
a = new char[size + 1];
strcpy(a,s.a);
return *this;
}
}
String::~String(){
delete[] a;//是这个析构函数不对还是下面这个+=运算符有问题呢?还是别的原因?
}

String& String::operator+=(const String& s){
int j = strlen(a);
size = j + strlen(s.a);
int m = size + 1;
char* b = new char[j+1];
strcpy(b,a);
a = new char[m];
//strcpy(a,b);
int i = 0;
while(i < j){
a[i] = b[i];
i++;
}
delete[] b;

int k = 0;
while(j < m){
a[j] = s[k];
j++;
k++;
}
a[j] = '\0';

return *this;

}

int String::length(){
return strlen(a);
}

main.cpp:

#include <iostream>
#include "String.h"

using namespace std;

bool operator==(const String& left, const String& right)
{
int a = strcmp(left.a,right.a);
if(a == 0)
return true;
else
return false;
}
bool operator!=(const String& left, const String& right)
{
return !(left == right);
}

ostream& operator<<(ostream& os,String& s){
int length = s.length();
for(int i = 0;i < length;i++)
//os << s.a[i];这么不行,私有变量.
os << s[i];
return os;
}


String operator+(const String& a,const String& b){
String temp;
temp = a;
temp += b;
return temp;

}

bool operator<(const String& left,const String& right){

int j = 0;
while((left[j] != '\0') && (right[j] != '\0')){
if(left[j] < right[j])
return true;
else
{
if(left[j] == right[j]){
j++;
continue;
}
else
return false;
}
}
if((left[j] == '\0') && (right[j] != '\0'))
return true;
else
return false;
}

bool operator>(const String& left, const String& right)
{ int a = strcmp(left.a,right.a);
if(a > 0)
return true;
else
return false;

}

istream& operator>>(istream& is, String& s){
delete[] s.a;
s.a = new char[20];
int m = 20;
char c;
int i = 0;
while (is.get(c) && isspace(c));
if (is) {
do {s.a[i] = c;
i++;
/*if(i >= 20){
cout << "Input too much characters!" << endl;
exit(-1);
}*/
if(i == m - 1 ){
s.a[i] = '\0';
char* b = new char[m];
strcpy(b,s.a);
m = m * 2;
s.a = new char[m];
strcpy(s.a,b);
delete[] b;
}
}
while (is.get(c) && !isspace(c));
//如果读到空白,将其放回.
if (is)
is.unget();
}
s.size = i;
s.a[i] = '\0';
return is;
}


int main(){
String a = "abcd";
String b = "www";
//String c(6,b);这么写不对.
String c(6,'l');
String d;
String e = a;//abcd
String f;
cin >> f;
String g;
g = a + b;//abcdwww

if(a < b)
cout << "a < b" << endl;
else
cout << "a >= b" << endl;
if(e == a)
cout << "e == a" << endl;
else
cout << "e != a" << endl;

b += a;

cout << a << endl;
cout << b << endl;
cout << c << endl;
cout << d << endl;
cout << e << endl;
cout << f << endl;
cout << g << endl;
cout << g[0] << endl;
return 0;
}

按理析构函数应该没错啊,希望高手来指点一下,谢谢.
















...全文
681 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
aflyinghorse 2005-10-21
  • 打赏
  • 举报
回复
私有变量在类的内部是可以访问的,直接用就行,和友元没关系。
可以看c++ primer,里面讲的很清楚
wanguodu 2005-10-21
  • 打赏
  • 举报
回复
喔,不好意思,说得不够准确,应该是:
一个类的成员函数可以访问同类对象的私有成员.见下面的链接:
http://community.csdn.net/Expert/topic/4315/4315700.xml?temp=.9136621
http://community.csdn.net/Expert/topic/4172/4172609.xml?temp=.7569391
duduhaha 2005-10-21
  • 打赏
  • 举报
回复
一个类的对象可以访问同类对象的私有成员,这个以前有很多讨论的.
这个是为什么啊,是规定还是什么?讨论很多?小弟新来的,呵呵.麻烦给个链接看看,或者详细解释一下,多谢了.
wanguodu 2005-10-21
  • 打赏
  • 举报
回复
一个类的对象可以访问同类对象的私有成员,这个以前有很多讨论的。另外,s.a是cha *的,当然可以作为strlen的参数了。
duduhaha 2005-10-21
  • 打赏
  • 举报
回复
多谢aflyinghorse和wanguodu.确实是越界的问题,昨天写这个写得头都晕了,在那个while循环中把m改成size也行:)
还有一个问题,在下面函数中.
String::String(const String& s){
size = strlen(s.a);//可以访问私有变量.
a = new char[size + 1];
strcpy(a,s.a);
}
为啥strlen函数中可以用s.a啊?a是私有变量啊.我以前听说好像是友元类的关系吧.不知道是不是?恳请具体说明白一下,非常感谢.
wanguodu 2005-10-21
  • 打赏
  • 举报
回复
楼上的, 肯定是越界了:
int k = 0;
while(j < m){
a[j] = s[k];
j++;
k++;
}
//这时j=m=size+1了
a[j] = '\0';
应改为:
int k = 0;
while(j < m-1){
a[j] = s[k];
j++;
k++;
}
//这时j=m=size+1了
a[j] = '\0';



aflyinghorse 2005-10-21
  • 打赏
  • 举报
回复
可能是越界了

int k = 0;
while(j < m){
a[j] = s[k];
j++;
k++;
}

//a[j] = '\0'; 这行注释掉试试

wanguodu 2005-10-21
  • 打赏
  • 举报
回复
还有就是将我的main函数中的几个重载运算符移到String.h文件中编译为啥就不能通过呢?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp和String.cpp都包含该头文件,相当于在两个源文件中定义了同样的函数,当然编译不通过了。
wanguodu 2005-10-21
  • 打赏
  • 举报
回复
aflyinghorse() 的+=实现也存在size成员没有更新的问题!
duduhaha 2005-10-21
  • 打赏
  • 举报
回复
还有就是将我的main函数中的几个重载运算符移到String.h文件中编译为啥就不能通过呢?
错误提示如下:
error LNK2005: "bool __cdecl operator==(class String const &,class String const &)" (??8@YA_NABVString@@0@Z) already defined in main.obj
好像是如果定义在String.h中,会与std中的==相冲突,那怎样才能避免呢?也就是怎样才能编译通过呢.
wanguodu 2005-10-21
  • 打赏
  • 举报
回复
操作符+=的实现有问题,改为下面的试一试:

String& String::operator+=(const String& s)
{
char *tmp = new char[size+1];
assert(tmp != NULL);
strcpy(tmp, a); //先备份一下a

delete[] a;

size += s.size;
a = new char[size+1];
assert(a != NULL);

strcpy(a, tmp);
strcat(a, s.a);

delete[] tmp;
}

楼主的程序中定义了局部变量int size,但类的成员size却未更新!
duduhaha 2005-10-21
  • 打赏
  • 举报
回复
真是奇怪啊.我原本是想在+=那个函数中不采用strcpy函数而自己用while语句一个一个赋值实现strcpy的,所以把它搞复杂了.
不过按aflyinghorse的实现方法确实问题就没了.但我真没从那个较复杂的实现方案找到毛病,请
aflyinghorse看看,多谢了.
duduhaha 2005-10-21
  • 打赏
  • 举报
回复
顶一个...
aflyinghorse 2005-10-21
  • 打赏
  • 举报
回复
我觉得你的operator+= 写的太复杂了,下面这样可不可以
(没有调试过)

String& String::operator+=(const String& s){
int j = strlen(a);
int size = j + strlen(s.a);
char* tmp = new char[size+1];
strcpy(tmp,a);
strcpy(tmp+j,s.a);
delete[] a;
a = tmp;
}

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧