String 類實現 以及>> <<流插入/流提取運算符重載


簡單版的String類,旨在說明>> <<重載

#include <iostream>
//#include <cstring>//包含char*的字符串處理函數
using namespace std;

class String
{
public:
    String(){p=NULL;}
    String(char *str);
    void diaplay();
    friend bool operator>(String &str1,String &str2);//重載>操作符
    friend ostream & operator <<(ostream&,String &str);
    friend istream & operator >>(istream&,String &str);
private:
    char *p;
};
String::String(char *str)
{
    p=str;
}
void String::diaplay()
{
    cout<<p;
}
bool operator>(String &str1,String &str2)
{
    if (strcmp(str1.p,str2.p)>0)
    {
        return true;
    }
    else return false;
}
ostream& operator <<(ostream& output,String &str)
{
    output<<str.p;
    return output;
}
istream& operator >>(istream& input,String &str)
{
    //input>>str.p;//沒有分配空間,無法讀入。
    str.p=new char[256];
    input>>str.p;
    return input;//
//     char q[256];  
//     input>>q;  
//     //p.length =strlen(q);  
//     str.p=new char[strlen(q)+1];  
//     strcpy(str.p,q);  
//     return input;

}
int main()
{
    String str1("Hello,pig!"),str2;
    cin>>str2;
    str1.diaplay();
    bool b=str1>str2;
    cout<<'\n'<<b<<endl;
    cout<<str2<<endl;
}

重載>> <<函數只能作為類的類的友元函數,其形式如下:

istream& operator >>(istream& ,自定義類 &);

ostream& operator <<(ostream& ,自定義類 &); 

重載運算法作為類成員函數還是類友元函數區別:

1 作為類成員函數必須滿足運算表達式第一個參數是一個類對象,而且返回值與該對象同類型。

故一般將單目操作符重載為成員函數,雙目操作符重載為友元函數。

String 類較完整實現:

 

#include <iostream>
//#include <cstring>//包含char*的字符串處理函數
using namespace std;

class String
{
public:
    String(){p=NULL;len=0;}
    String(int);
    String(char *str);
    String (String&);
    ~String(){delete[] p;}
    void Clear();//清空本串
    int mystrlen();
    bool IsEmpty();//判斷本串是否為空
    String Substr(int index,int count);//從index開始提取count個字符的字串
    int Find(char c,int start);//從下標start開始找到c后,返回字符c 在本串的下標
    char & operator [](int i);//重載[]操作符
    operator char *();//將String類對象轉換為普通字符串

    friend bool operator>(String &str1,String &str2);//重載>操作符
    friend ostream & operator <<(ostream&,String &str);
    friend istream & operator >>(istream&,String &str);
private:
    char *p;//字符串指針
    int len;//字符串長度,不包含最后的\0
};

String::String(int length)
{
    len=length;
    p=new char[length+1];
}
String::String(char *str)
{
    if (str==NULL)
    {
        len=0;
        p=NULL;
    }
    else
    {
        len=strlen(str);
        p=new char[len+1];
        strcpy(p,str);//深拷貝
    }
    //p=str;//只寫這個是淺拷貝,只拷貝了指針
}
String::String(String &other)
{
    len=other.len;
    p=new char[len+1];
    strcpy(p,other.p);
}
bool String::IsEmpty()
{
    return (!this->len);
}

void String::Clear()
{
    if (!IsEmpty())
    {
        delete[]p;
        len=0;
    }
}
int String::mystrlen()
{
    return len;
}
int String::Find(char c,int start)
{
     int i;
    if (start>len) cout<<"超出范圍"<<endl;
    //return NULL;
    else
        {
            for (i =start;i<len;++i)
            {
                if (p[i]==c) break;
             }
            return i;
    
          }
}
String String::Substr(int index,int count)
{
    
    if (index+count>len) cout<<"超出范圍"<<endl;
    else
    {
        String str(count);
        str.len=count;
        for (int i=0;i<count;i++,index++)
            str.p[i]=p[index];

            str.p[count]='\0';
            return str;
    }
    
}
char & String::operator[](int i)
{
    if (i<0||i>len-1)
    {
        cout<<"越界"<<endl;
    }
    else
    {
        return p[i];
    }
}
//類型轉換
String::operator char *()
{
    return (char *)p;
}

bool operator>(String &str1,String &str2)
{
    if (strcmp(str1.p,str2.p)>0)
    {
        return true;
    }
    else return false;
}
ostream& operator <<(ostream& output,String &str)
{
    output<<str.p;
    return output;
}
istream& operator >>(istream& input,String &str)
{
    //input>>str.p;//沒有分配空間,無法讀入。
    str.p=new char[256];
    input>>str.p;
    return input;//
    //或者:
//     char q[256];  
//     input>>q;    
//     str.p=new char[strlen(q)+1];  
//     strcpy(str.p,q);  
//     return input;

}
int main()
{
    String str3("hello");  
    int pos;  
    cout<<"\n測試Find功能"<<endl;  
    pos = str3.Find('e',0);  
    cout<<str3<<endl;  
    cout<<pos<<endl;  
     
    cout<<"\n測試Substr功能"<<endl;  
    cout<<str3.Substr(1,2)<<endl;  
      
    cout<<"\n測試重載<< >>功能"<<endl;  
    String c;  
    cout<<"請輸入一段字符串"<<endl;  
    cin>>c;  
    cout<<c<<endl;  
     
    cout<<"測試字符串C函數的應用"<<endl;  
    String f(40);  
    char *e = " this is a test";  
    char g[50]="hahahhah";
    strcpy(f,e); //隱含執行了默認類型轉換(char *)f; 
    cout<<f<<endl;  
    strcat(g,f);  
    cout<<g<<endl; 

    cout<<"\n測試IsEmpty _strlen功能"<<endl;  
    String d("tihs is a test");  
    if(d.IsEmpty())  
        cout<<"d 是空字符串"<<endl;  
    else  
        cout<<"d 非空字符串 \t長度:"<<d.mystrlen()<<endl;  
      
    return 0;  

}

注意:C++標准庫中string類構造函數是淺拷貝,

 string a="hello";
 string b(a);
 cout<<(void *)a[2]<<endl;
 cout<<(void *)b[2]<<endl; 地址形同


注意:operator char *();//將String類對象轉換為普通字符串  

是類型轉換函數的定義,即該類型可以自動轉換為const char*類型。

像是隱式類型轉換

不同於重載*,重載*應寫為 char operator * ();

因為運算符重載中有幾個運算符的返回值是有格式的(約定),如operator * 在重載時通常返回值是classType&或者const classType& 。
operator const char*() const是類型轉換函數的定義,即該類型可以自動轉換為const char*類型。至於最后一個const,那個大家都知道是對類成員的限制(不允許更改對象的狀態)
比如我們現在自定一個一個整型(MyInt),它允許在需要使用C++語言中的int類型時將MyInt類型轉換為int類型:
class MyInt {
     public:
          operator int () const;
     private:
          int elem;
};
MyInt::operator int () const
{
    return elem;
}
就可以在需要使用int類型時使用MyInt。
需要記住,C++中沒有返回類型的函數有3個,構造函數、析構函數、類型轉換函數。

前兩個是不寫返回類型函數實現中也不允許出現return語句
最后一個則是不寫返回類型,但是必須返回對應類型的值,即必須出現return語句。

 

類型轉換中返回類型在operator后面在括號前面,且沒有參數。

函數運算符中是類型在operator 前面

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM