2012-03-08 72 views
1

我想写我自己的getline函数,并保持segfaulting。我该如何解决这个问题,如果我的工作不正常,怎么才能正常工作?我正在写这个来学习如何更好地编写代码。获取线路如何工作?

#include"MyString.h" 





MyString::MyString() //constructor 
{ 
    size=0; 
    capacity=1; 
    data=new char[capacity]; 

} 
MyString::MyString(char * n) //copy constructor 
{ 
    size=strlen(n); 
    capacity=strlen(n)+1; 
    data=new char[capacity]; 
    strcpy(data,n); 
} 
MyString::MyString(const MyString &right) // 
{ 
    size=strlen(right.data); 
    capacity=strlen(right.data)+1; 
    data=new char [capacity]; 
    strcpy(data,right.data); 

} 
MyString::~MyString() 
{ 
    delete [] data; 
} 
MyString MyString::operator = (const MyString& s) 
{ 

    if(this!=&s) 
    { 
     MyString temp=data; 
     delete [] data; 
     size=strlen(s.data); 
     capacity=size+1; 
     data= new char [capacity]; 
     strcpy(data,s.data); 
    } 
} 
MyString& MyString::append(const MyString& s) 
{ 
    if(this!=&s) 
    { 
     strcat(data,s.data); 
    } 


} 
MyString& MyString::erase() 
{ 

} 
MyString MyString::operator + (const MyString& s)const 
{ 
    return strcat(data,s.data); 
} 
bool MyString::operator == (const MyString& s) 
{ 
    return strcmp(data,s.data)==0; 
} 
bool MyString::operator < (const MyString& s) 
{ 
    return strcmp(data,s.data)<0; 
} 
bool MyString::operator > (const MyString& s) 
{ 
    return strcmp(data,s.data)>0; 
} 
bool MyString::operator <= (const MyString& s) 
{ 
    return strcmp(data,s.data)<=0; 
} 
bool MyString::operator >= (const MyString& s) 
{ 
    return strcmp(data,s.data)>=0; 
} 
bool MyString::operator != (const MyString& s) 
{ 
    return strcmp(data,s.data)!=0; 
} 
void MyString::operator += (const MyString& s) 
{ 
    append(s.data); 
} 
char& MyString::operator [ ] (int n) 
{ 
    return data[n]; 
} 
void MyString::getline(istream& in) 
{ 
    char c; 
    erase(); 
    ifstream input; 
    while(in.get(c)&&c!='\n') 
    { 
     data[size]=c; 
     size++; 

     if(size+1<=capacity) 
     { 
      capacity*=2; 
      char*p=new char[capacity]; 
      strcpy(p,data); 
      delete [] data; 
      data=p; 
     } 
     data[size]=c; 
     size++; 
     data[size]='\0'; 
    } 

} 
int MyString::length() const 
{ 
    return strlen(data); 
} 
void MyString::grow() 
{ 
capacity=strlen(data)+1; 
MyString temp; 
temp=data; 
delete [] data; 
capacity*=2; 
data= new char[capacity]; 
} 

ostream& operator<<(ostream& out, MyString& s) 
{ 

    out<<s.data; 
    return out; 


} 



// int MyString::getCapacity(){return capacity;} 
+0

不分段错误发生在哪一行? – 2012-03-08 04:03:21

+0

对于你的concat/append运算符,你不觉得你应该调整你的数据数组的大小来保存新的字符串吗? – indiv 2012-03-08 04:19:03

+0

'MyString :: MyString(char *)'不是一个拷贝构造函数。 – 2012-03-08 04:19:04

回答

0

它应该是这个样子:

void MyString::getline(istream& in) 
{ 
    erase(); 
    for (char c; in.get(c) && c != '\n';) 
     append(c); 
} 

现在你只需要正确地实现一个名为追加方法追加单个字符。如果您遇到问题,请提出另一个问题。你可能会认为我在这里很滑稽,但我不是。您需要限制您重新分配的位置,并停止在代码中重复自己。 getline函数不是那种活动的地方(我的意思是重新分配)。

+0

'for'循环最好是'while'循环:'char c; while(in.get(c)&& c!='\ n')追加(c);' – 2012-03-08 04:45:00

1

嗯......

if(size+1<=capacity) 

比方说,你的能力是11,你的尺寸是11

if(12 <= 11) 
{ 
    // Resize capacity. This code won't run. 
} 

你想if(size >= capacity)

此外,你有data[size] = c; size++;在你的循环中两次。所以你要制作每个角色的2份副本。

0
MyString::MyString(char * n) //copy constructor 
{ 
    size=strlen(n); 
    capacity=strlen(n)+1; 
    data=new char[capacity]; 
    strcpy(data,n); 
} 

有两次没有要求strlen。优化器不够聪明以消除冗余。另外,由于您没有更改传入字符串中的数据,因此应该是const。否则,你无法传递它的字符串常量。固定,我们得到:

MyString::MyString(const char * n) //copy constructor 
{ 
    size = strlen(n); 
    capacity = size + 1; 
    data = new char[capacity]; 
    strcpy(data, n); 
} 

MyString::MyString(const MyString &right) // 
{ 
    size=strlen(right.data); 
    capacity=strlen(right.data)+1; 
    data=new char [capacity]; 
    strcpy(data,right.data); 

} 

rightsize成员,消除了strlen的需要。这加上上述修正给:

MyString::MyString(const MyString &right) // 
{ 
    size = right.size; 
    capacity = size + 1; 
    data = new char[capacity]; 
    strcpy(data, right.data); 
} 

MyString MyString::operator = (const MyString& s) 
{ 

    if(this!=&s) 
    { 
     MyString temp=data; 
     delete [] data; 
     size=strlen(s.data); 
     capacity=size+1; 
     data= new char [capacity]; 
     strcpy(data,s.data); 
    } 
} 

operator =应该返回一个引用(即*this;顺便说一句,你忘了返回任何东西),而不是另一个副本。还要注意的是temp不使用,和你有一个多余的strlen电话:

MyString& MyString::operator = (const MyString& s) 
{ 
    if(this!=&s) 
    { 
     delete[] data; 
     size = s.size; 
     capacity = size + 1; 
     data = new char[capacity]; 
     strcpy(data, s.data); 
    } 
    return *this; 
} 

MyString& MyString::append(const MyString& s) 
{ 
    if(this!=&s) 
    { 
     strcat(data,s.data); 
    } 


} 

你忘了检查sizecapacity。因此strcat将会从您的char阵列的末端运行。此外,应该使自身连接起作用。而你并不需要strcat

MyString& MyString::append(const MyString& s) 
{ 
    size_t rSize = s.size; 
    if(capacity < size + rSize + 1) 
    { 
     capacity = size + rSize + 1; 
     char* newData = new char[capacity]; 
     memcpy(newData, data, size); 
     delete[] data; 
     data = newData; 
    } 
    memcpy(data + size, s.data, rSize); 
    size += rSize; 
    data[size] = '\0'; 
    return *this; 
} 

erase只需使字符串消失。没有记忆需要被搞砸:

MyString& MyString::erase() 
{ 
    size = 0; 
    data[0] = '\0'; 
} 

MyString MyString::operator + (const MyString& s)const 
{ 
    return strcat(data,s.data); 
} 

同样的问题与append,加上这一项应该返回一个新对象,并独自离开它的输入。此外,重用迄今已写入的方法:

MyString MyString::operator + (const MyString& s) const 
{ 
    return MyString(*this).append(s); 
} 

void MyString::operator += (const MyString& s) 
{ 
    append(s.data); 
} 

这是一个阴险的一个!见,因为append需要const MyString&但你给它一个char*,编译器会创建一个临时MyString,调用MyString(const char*)构造函数就可以了,通过临时到append,然后将其丢弃。所以你得到了正确的结果,但你创建了一个额外的对象。正确的做法是:

void MyString::operator += (const MyString& s) 
{ 
    append(s); 
} 

char& MyString::operator [ ] (int n) 
{ 
    return data[n]; 
} 

不进行边界检查?勇敢。如果你想要它,不难添加。假设你不想抛出异常:

char& MyString::operator [] (int n) 
{ 
    if(n < 0) 
     n = 0; 
    if(n >= size) 
     n = size - 1; 
    return data[n]; 
} 

仅供参考,一般类型的指数是size_t,这是在<stddef.h>定义,是sizeof()返回的无符号整型,所以它的保证,因为上班一个数组索引与一个正常的数组(在这里,你可以摆脱负指数检查)。

此外,您可能需要一个可以在const MyString上工作的版本。它只是返回字符,而不是一个参考:

char MyString::operator [] (int n) const 
{ 
    if(n < 0) 
     n = 0; 
    if(n >= size) 
     n = size - 1; 
    return data[n]; 
} 

void MyString::getline(istream& in) 
{ 
    char c; 
    erase(); 
    ifstream input; 
    while(in.get(c)&&c!='\n') 
    { 
     data[size]=c; 
     size++; 

     if(size+1<=capacity) 
     { 
      capacity*=2; 
      char*p=new char[capacity]; 
      strcpy(p,data); 
      delete [] data; 
      data=p; 
     } 
     data[size]=c; 
     size++; 
     data[size]='\0'; 
    } 

} 

首先,ifstream什么也不做;摆脱它。您应该只使用istream。个人指出了额外字符和错误检查的问题。该strcpy将失败,因为你还没有提上了弦的末尾\0回来,所以你需要使用memcpy代替:

void MyString::getline(istream& in) 
{ 
    char c; 
    erase(); 
    while(in.get(c) && c != '\n') 
    { 
     data[size++] = c; 
     if(size >= capacity) 
     { 
      capacity *= 2; 
      char *newData = new char[capacity]; 
      memcpy(newData, data, size); 
      delete[] data; 
      data = newData; 
     } 
    } 
    data[size] = '\0'; 
} 

int MyString::length() const 
{ 
    return strlen(data); 
} 

这只是在浪费时间,因为size已经有字符串的长度。它真的应该在类定义来定义,因此它可以被内联:

int MyString::length() const 
{ 
    return size; 
} 

void MyString::grow() 
{ 
capacity=strlen(data)+1; 
MyString temp; 
temp=data; 
delete [] data; 
capacity*=2; 
data= new char[capacity]; 
} 

第一行是完全错误的; capacity已经设置正确。您不需要temp。和俞忘了字符串数据拷贝过来:

void MyString::grow() 
{ 
    capacity *= 2; 
    char* newData = new char[capacity]; 
    memcpy(newData, data, size + 1); 
    delete[] data; 
    data = newData; 
} 

ostream& operator<<(ostream& out, MyString& s) 
{ 

    out<<s.data; 
    return out; 


} 

你不改变s,所以它应该是const

ostream& operator<<(ostream& out, const MyString& s) 
{ 
    return out << s.data; 
}