亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

代碼分析c++中string類

2020-05-23 13:34:11
字體:
來源:轉載
供稿:網友

一:回顧

(1)c++中的string類是在面試中和筆試中經??嫉念}目; 工程代碼免費下載 string類的自行實現

(2)c++中的string類和fstream類合起來是處理外部數據的利器;

(3)string類經常用到find find_first_of find_first_not_of find_last_of find_last_not_of substr replace等,以及聯合使用來達到java中的split和trim

(4) 使用friend 僅僅是在類中進行聲明的非內部 卻可以訪問內部成員的外部函數,而且在外部不再需要friend關鍵字;它與成員函數的區別是,friend和外部函數不含有this對象指針;本文用到了const 定義的全局最大值最小值變量(代替#define)

(5) 有些函數返回的是MyString& 、Char& 等(引用),MyString、Char 等(傳值)這得看你返回的對象是函數的局部變量還是全局變量(或者類當前對象成員變量);前者只能返回一個MyString、Char 等;后者強烈建議返回MyString& 、Char& 等(引用);

(6)有些函數的參數是const MyString& ,有些是MyString& (引用);這是為什么?前者是把外部值傳提到子函數內部,且不允許改變;后者是作為函數的返回值傳遞進去的,返回的結果為函數的處理結果(而不用函數自身返回值了)。

二:下面是簡單的實現了一下string類,參照的是STL源碼,但是自己理解的還是不夠深,難免有一些錯誤,請各位指教

(1)MyString.h文件

#ifndef MYSTRING_H#define MYSTRING_H#include "MyExcept.h"#include <cstring>#include <iostream>const int INI_MAX = 0x7fffffff;//2^32nposconst int INI_MIN = 0x80000000;// -2^32const int npos = 0xffffffff;// nposusing namespace std;class MyString{  public:  // constructor  MyString();//  MyString(const MyString &);//  MyString(const char *);  MyString(const size_t,const char);  // destructor  ~MyString();  // attributes  size_t length();// 字符串長度  bool isEmpty();// 返回字符串是否為空  const char* c_str();// 返回c風格的trr的指針  // friend funs  // read writer operations  friend ostream& operator<< (ostream&, const MyString&);  friend istream& operator>> (istream&, MyString&);  //add operation  friend MyString operator+(const MyString&,const MyString&);  // compare operations  friend bool operator==(const MyString&,const MyString&);  friend bool operator!=(const MyString&,const MyString&);  friend bool operator<(const MyString&,const MyString&);  friend bool operator<=(const MyString&,const MyString&);  friend bool operator>(const MyString&,const MyString&);  friend bool operator>=(const MyString&,const MyString&);  // 成員函數實現運算符重載,其實一般需要返回自身對象的,成員函數運算符重載會好一些  // index operation  char& operator[](const size_t);  const char& operator[](const size_t)const;  // =  MyString& operator=(const MyString&);  // +=  MyString& operator+=(const MyString&);  // +=  //MyString operator+=(const MyString&); cannot be overloaded  // 成員操作函數  // substr  MyString substr(size_t pos,const size_t n);  // append  MyString& append(const MyString&);  //insert  MyString& insert(size_t,const MyString&);  //assign 替換  MyString& assign(MyString&,size_t,size_t);  // erase 刪除  MyString& erase(size_t,size_t);  //find_first_of 查找某一個字符 size_t 是非符號數的,重載  // 查找在字符串中第一個與str中的某個字符匹配的字符,返回它的位置。  //搜索從index開始,如果沒找到就返回string::npos  int find_first_of(const char* str,size_t index=0);  int find_first_of(const char ch,size_t index=0);  int find_first_of(const MyString &,size_t index=0);  // 在字符串中查找第一個與str中的字符都不匹配的字符,返回它的位置。搜索從index開始。如果沒找到就返回string::nops  int find_first_not_of(const char* str,size_t index=0);  int find_first_not_of(const char ch,size_t index=0);  int find_first_not_of(const MyString&,size_t index=0);  // swap  void swap(MyString& lhs,MyString& rhs);  // replace_all  MyString& replace_all(const char oldc,const char newc=NULL);  MyString& replace(size_t index,size_t num1,size_t num2,const char ch);  //find  int find(const char* str,size_t index=0);  int find(const MyString& str,size_t index=0);  int find(const char ch,size_t index=0);  //private  private:  char *p_str;  size_t strLength;};#endif // MYSTRING_H

(2)MyString.cpp文件

#include "MyString.h"#include <cassert>// constructor  MyString::MyString():p_str(NULL),strLength(0){}  MyString::MyString(const MyString &str)//  {    if(NULL == str.p_str)    {      return;    }    strLength = str.strLength;    p_str = new char[strLength+1];    strcpy(p_str,str.p_str);  }  MyString::MyString(const char *str)  {    if(NULL == str)    {      return;    }    strLength = strlen(str);    p_str = new char[strLength+1];    strcpy(p_str,str);  }  MyString::MyString(const size_t len,const char ch)  {    if(NULL == ch)    {      return;    }    strLength = len;    p_str = new char[strLength+1];    for(size_t i=0;i<strLength;i++)    {      p_str[i] = ch;    }    p_str[strLength] = '/0';// 因為strset以'/0'結束的    cout << p_str << " &&" << endl;    //strset(p_str,ch);    //cout << p_str[0] << ",,,"<<strlen(p_str) << "," << strLength << endl;  }  // destructor  MyString::~MyString()  {    delete[] p_str;  }  // attributes  size_t MyString::length()// 字符串長度  {    return strLength;  }  bool MyString::isEmpty()// 返回字符串是否為空  {    return strLength==0?true:false;  }  const char* MyString::c_str()  {    return p_str;  }  // 為什么不是引用呢??? friend 使用在類里面進行聲明的,外面就不需要了,而且友元函數不屬于類的成員函數,所以不用MyString::  // ostream  ostream& operator<< (ostream& out,const MyString &str)  {    if(str.p_str != NULL)    {      out << str.p_str;    }    return out;  }  // istream,一個是const另一個不是,根據變還是不變  istream& operator>> (istream& in, MyString& str)  {    char tmp[100];// 臨時字符串    if(in>>tmp)    {      delete[] str.p_str;      str.strLength = strlen(tmp);      str.p_str = new char[str.strLength+1];      strcpy(str.p_str,tmp);    }    return in;  }  // + 加  MyString operator+(const MyString& lhs,const MyString& rhs)  {    MyString ret;    ret.strLength = lhs.strLength + rhs.strLength;    ret.p_str = new char[ret.strLength+1];    strcpy(ret.p_str,lhs.p_str);    strcat(ret.p_str,rhs.p_str);    return ret;  }  // compare operations  bool operator==(const MyString& lhs,const MyString& rhs)  {    return strcmp(lhs.p_str,rhs.p_str)==0?true:false;  }  bool operator!=(const MyString& lhs,const MyString& rhs)  {    return strcmp(lhs.p_str,rhs.p_str)!=0?true:false;  }  bool operator<(const MyString& lhs,const MyString& rhs)  {    return strcmp(lhs.p_str,rhs.p_str)<0?true:false;  }  bool operator<=(const MyString& lhs,const MyString& rhs)  {    return strcmp(lhs.p_str,rhs.p_str)<=0?true:false;  }  bool operator>(const MyString& lhs,const MyString& rhs)  {    return strcmp(lhs.p_str,rhs.p_str)>0?true:false;  }  bool operator>=(const MyString& lhs,const MyString& rhs)  {    return strcmp(lhs.p_str,rhs.p_str)>=0?true:false;  }  // 成員函數實現運算符重載  // index operation  char& MyString::operator[](const size_t index)  {    if(index<0 || index>=strLength)    {      throw Outofbond() ;    }    return p_str[index];  }  const char& MyString::operator[](const size_t index)const  {    if(index<0 || index>=strLength)    {      throw Outofbond();    }    return p_str[index];  }   // = 賦值構造函數(判斷是否是自身) 為什么要這樣刪除呢?  MyString& MyString::operator=(const MyString& other)  {    if(this != &other)    {      if(strLength<other.strLength)      {        delete[] p_str;        p_str = new char[other.strLength+1];      }      strLength = other.strLength;      strcpy(p_str,other.p_str);    }// 這樣可能會產生多余的未釋放的空間    return *this;  }  // += 相當于返回的是備份的,內部對象的銷毀,不影響的 和 下面的完全不一樣的//  MyString MyString::operator+=(const MyString& other)//  {//    if(NULL == other.p_str)//    {//      return *this;//    }//    MyString ret;//    ret.strLength = strLength + other.strLength;//    ret.p_str = new char[ret.strLength+1];//    strcpy(ret.p_str,p_str);//    strcat(ret.p_str,other.p_str);//    return ret;//  }  // 返回的是當前對象的引用,當前對象就在調用函數里,所以不會銷毀的  // 判斷一下是否是自身相加  MyString& MyString::operator+=(const MyString& other)  {    if(NULL == other.p_str)    {      return *this;    }    if(this == &other)    {      MyString copy(*this);      return *this += copy;    }// 必須判斷是否相等的,而且要+=的,這樣相當于調用了自身,但是這次直接下面去了,不進入if的    strLength += other.strLength;    //strLength *= 2;    char *p_old = p_str;    p_str = new char[strLength+1];    strcpy(p_str,p_old);    strcat(p_str,other.p_str);    delete[] p_old;// 刪除舊的空間    return *this;  }  // 成員操作函數  // substr 返回應用是不行的,錯誤的;取從pos開始的n個字符組成的子串  //MyString& MyString::substr(size_t pos,const size_t n)  MyString MyString::substr(size_t pos,const size_t n)  {    if((pos+n)>=strLength)    {      throw Outofbond();    }    MyString ret;    ret.strLength = n;    //ret.p_str = new char[n+1];    ret.p_str = new char[ret.strLength+1]; //也可以    for(size_t i=0;i<n;i++)    {      ret.p_str[i] = p_str[pos+i];    }    ret.p_str[n] = '/0';//    for(size_t i=0;i<ret.strLength;i++)//    {//      ret[i] = (*this)[pos+i];//      cout << ret[i] << ",,";//    }// 也行的,利用剛剛重載的【】,這樣更好,不用再次判斷越界了,不知道為什么,報錯誤的//    ret[ret.strLength] = '/0';    return ret;  }  // append 同 += 追加到末尾  MyString& MyString::append(const MyString& other)  {    *this += other;// 利用剛剛那重載的+=    return *this;  }  //insert 從pos開始的插入other  MyString& MyString::insert(size_t pos,const MyString& other)  {    if(pos<0 || pos>=strLength)    {      throw Outofbond();    }    char *p_old = p_str;    strLength += other.strLength;    p_str = new char[strLength+1];    for(size_t i=0;i<pos;i++)    {      *(p_str+i) = *(p_old+i);    }    for(size_t i=pos;i<other.strLength+pos;i++)    {      *(p_str+i) = other.p_str[i-pos];    }    for(size_t i=other.strLength+pos;i<strLength;i++)    {      *(p_str+i) = p_old[i-other.strLength];    }    *(p_str+strLength) = '/0';    return *this;  }  //assign 替換 用other的POS開始的n對應替換this的pos開始的  MyString& MyString::assign(MyString&other,size_t pos,size_t n)  {//    if(pos<0 || pos>=strLength)//    {//      throw Outofbond();//    }    assert(pos>0 && pos<strLength);// assert 的好處    assert(pos+n<other.strLength);    if(strLength < pos + n)    {      char *p_old = p_str;      strLength = pos + n;      p_str = new char[strLength+1];      for(size_t i=0;i<pos;i++)      {        *(p_str+i) = *(p_old+i);      }      delete[] p_old;    }    for(size_t i=pos;i<pos+n;i++)    {      *(p_str+i) = other.p_str[i];    }    *(p_str+pos+n) = '/0';    return *this;  }  // erase 刪除 這個方法并不是很好的,并沒有釋放所erase的空間,請看下面的//  MyString& MyString::erase(size_t pos,size_t n)//  {//    if((pos+n)>strLength)//    {//      throw Outofbond();//    }//    size_t index = pos + n;//    while(*(p_str+index)!='/0')//    {//      *(p_str+index-n) = *(p_str+index);//      ++index;//    }//    *(p_str+index-n) = '/0';//    return *this;//  }  // erase 刪除 從pos開始的n個字符  MyString& MyString::erase(size_t pos,size_t n)  {    if((pos+n)>strLength)    {      throw Outofbond();    }    char *p_old = p_str;    strLength -= n;    p_str = new char[strLength+1];    for(size_t i=0;i<pos;i++)    {      p_str[i] = p_old[i];    }    for(size_t i=pos;i<strLength;i++)    {      p_str[i] = p_old[i+n];    }    *(p_str+strLength) = '/0';    return *this;  }  //find_first_of 查找某一個字符 size_t 是非符號數的  // 查找在字符串中第一個與str中的某個字符匹配的字符,返回它的位置。  //搜索從index開始,如果沒找到就返回string::npos  int MyString::find_first_of(const char* str,size_t index)  {    if(NULL == str || index >=strLength)      return npos;    int tmp_len = strlen(str),j;    size_t flag,min_index = INI_MAX;    for(j=0;j<tmp_len;j++)    {      flag = npos;      for(size_t i=index;i<strLength;i++)      {        if(str[j] == p_str[i])        {          flag = i;          break;        }      }//      indexs[j] = flag;      if(flag != npos)      {        min_index = min_index<flag?min_index:flag;      }    }//    for(j=0;j<tmp_len;j++)//    {//      if(indexs[j]!=npos)//        min = min<indexs[j]?min:indexs[j];//    }    if(min_index == INI_MAX)    {      return npos;//      min_index = npos;//      cout << "---npos----" << min_index << ",,,,";    }    return min_index;  }  int MyString::find_first_of(const char ch,size_t index)  {    if(NULL == ch || index >=strLength)      return npos;    int j;    size_t flag = npos;    for(size_t i=index;i<strLength;i++)    {      if(ch == p_str[i])      {        flag = i;        break;      }    }    return flag;  }  int MyString::find_first_of(const MyString& str,size_t index)  {    if(NULL == str || index >=strLength)      return npos;    int j;    size_t flag,min_index = INI_MAX;    for(j=0;j<str.strLength;j++)    {      flag = npos;      for(size_t i=index;i<strLength;i++)      {        if(str[j] == p_str[i])        {          flag = i;          break;        }      }      if(flag != npos)      {        min_index = min_index<flag?min_index:flag;      }    }    if(min_index == INI_MAX)    {      return npos;    }    return min_index;  }  // 在字符串中查找第一個與str中的字符都不匹配的字符,返回它的位置。  //搜索從index開始。如果沒找到就返回string::nops O(N^2)  int MyString::find_first_not_of(const char *str,size_t index)  {    if(NULL == str || index >=strLength)      return npos;    size_t i=0,j=0;    size_t tmp_len = strlen(str);    for(i=index;i<strLength;i++)    {      for(;j<tmp_len;j++)      {        if(p_str[i]==str[j])          break;      }      if(j==tmp_len)        break;// 根據跳出的內層for的條件判斷,找到即結束循環    }    if(i==strLength)      return npos;// 未找到,// 根據跳出的內層for的條件判斷,找到即結束循環    return i;  }  int MyString::find_first_not_of(const MyString& str,size_t index)  {    if(NULL == str || index >=strLength)      return npos;    size_t i=0,j=0;    for(i=index;i<strLength;i++)    {      for(;j<str.strLength;j++)      {        if(p_str[i]==str[j])          break;// 如果相等 本輪i就無效了,進行下一輪      }      if(j==str.strLength)        break;// 根據跳出的內層for的條件判斷,找到即結束循環    }    if(i==strLength)      return npos;// 未找到,// 根據跳出的內層for的條件判斷,找到即結束循環    return i;  }  int MyString::find_first_not_of(const char ch,size_t index)  {    if(NULL == ch || index >=strLength)      return npos;    size_t i=0;    for(i=index;i<strLength;i++)    {      if(p_str[i]!=ch)// 跟上面的略微不同,找一個不等就可以了        break;    }    if(i==strLength)      return npos;// 未找到,// 根據跳出的內層for的條件判斷,找到即結束循環    return i;  }  // swap 都得變得,所以非const  void MyString::swap(MyString& lhs,MyString& rhs)  {    lhs.strLength ^= rhs.strLength;    rhs.strLength ^= lhs.strLength;    lhs.strLength ^= rhs.strLength;    char *p_tmp = rhs.p_str;    rhs.p_str = lhs.p_str;    lhs.p_str = p_tmp;  }  // replace_all 這個東西還是不太好弄的啊,不是很理想  MyString& MyString::replace_all(const char oldc,const char newc)  {    if(NULL == oldc)    {      return *(this);    }    for(size_t i=0;i<strLength;i++)    {      if(p_str[i] == oldc)      {        p_str[i] = newc;      }    }    return *(this);  }  MyString& MyString::replace(size_t index,size_t num1,size_t num2,const char ch)  {  }  // find 函數  int MyString::find(const char* str,size_t index)  {    assert(str!=NULL&&index<strLength);    // kmp 中的getnext函數    size_t len = strlen(str);    size_t next[len+1];    size_t j,k;    next[0] = npos;    j = 0;    k = npos;    while(j<len)    {      if(k==npos || str[j]==str[k])      {        j++;        k++;        next[j] = k;      }      else        k = next[k];    }    // kmp 算法    k = index;    j = 0;    while(p_str[k]!='/0')    {      if(j==0 || p_str[k]==str[j])      {        k++;        j++;      }      else      {        j = next[j];// 消除指針回溯      }      if(str[j] == '/0')//匹配成功        return k-j;    }    return npos;  }  int MyString::find(const MyString& str,size_t index)  {//    if(this == &str)//    {//      MyString other(*this);//      find(other,index);//    }    assert(NULL!=str && index<strLength);    // kmp 中的getnext函數    size_t next[str.strLength+2];    size_t j,k;    next[0] = npos;    j = 0;    k = npos;    while(j<str.strLength)    {      if(k==npos || str.p_str[j]==str.p_str[k])      {        j++;        k++;        next[j] = k;      }      else        k = next[k];    }    int i;    for(i=1;i<=j;i++)      cout << next[i] << ",";    // kmp 算法    k = index;    j = 0;    while(p_str[k]!='/0')    {      if(j==0 || p_str[k]==str.p_str[j])      {        k++;        j++;      }      else      {        j = next[j];// 消除指針回溯      }      if(str.p_str[j] == '/0')//匹配成功,不知道為什么調用自身的str[]重載總是報錯的        return k-j;    }    if(str.p_str[j] == '/0')// 同一個字符串      return k-j;    return npos;  }  int MyString::find(const char ch,size_t index)  {    assert(NULL!=ch && index<strLength);    for(size_t i=index;i<strLength;i++)    {      if(p_str[i] == ch)        return i;    }    return npos;  }

(3)測試函數main.cpp

#include "MyString.h"#include <iostream>using namespace std;int main(){  int n;  int choose = 1;  int p,l;  char cs[100];  MyString s1;  MyString s2("hello");  MyString s3 = "HELLO";  cout << "***** welcome *****/n";  cout << "******* MADE BY zyp **********/n";  cout << "s1= " << s1 << "s2= " << s2 << "s3= " << s3 << endl;  cout << "請輸入一個長度小于100的字符串:例如world/n";  cin >> s1;  s1 = s1;  //s1 = s1+s1;  s1 += s1;  MyString s4(s1);  s4.append(s1);  s2.insert(2,s3);  s1.erase(4,4);  s1.assign(s2,1,7);  cout << "s1= " << s1 << "s2= " << s2 << "s3= " << s3 << "s4= " << s4 << endl;  s2 = s4.substr(2,7);  cout << "s4[3]= " << s4[3] << s4.length() << (s1>=s2) << "s4.substr() " << s2 << endl;  cout << "s1.find_first_of(beLE,2):" << s1.find_first_of("beLE",2) << ",s1.find_first_of(a,3):" << s1.find_first_of('a',3) << ",s1.find_first_of(s3,2):" << s1.find_first_of(s3,2) << endl;  MyString s5(5,'b');  s5 += s5;  //s5.append(s5);// 不知道為什就是不能append  cout << "s5 = " << s5 << "s5.find_first_not_of(aeHLEOl,2):" << s5.find_first_not_of("aeHLEOl",2) << "s5.find_first_not_of(aeHLEOl,0):" << s5.find_first_not_of("aeHLEOl") << endl;  cout << "s5.find_first_not_of(s1,2):" << s5.find_first_not_of(s1,2) << "s5.find_first_not_of(b,2):" << s5.find_first_not_of('b',2) << endl;  swap(s1,s5);  s5.replace_all('a','J');  MyString s6("LLO");  cout << s1 << "," << s5 << "s5.find(LLO,0) " << s5.find("LLO",0) << "s5.find(s6,0) " << s5.find(s5) << endl;  cout << npos << endl;  return 0;}

三:感悟

(1)耗時將近2天的實現了它,自己與其從中學到了很多,倒不如說是重新認識了string類;

(2)自己知道這個簡單的string類,距離string源代碼還差的很遠很遠;但是它幫助我更好的理解了string類,至少會簡單的應用了。

(3)簡單的實現了一下string類,參照的是STL源碼,但是自己理解的還是不夠深,難免有一些錯誤,請各位指教,萬分感謝!

(4)下一步進軍list


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久婷婷国产麻豆91天堂| 欧美性生交xxxxx久久久| 亚洲精品色婷婷福利天堂| 亚洲成avwww人| 伊人久久五月天| 亚洲男人天堂视频| 日本精品va在线观看| 中文字幕久久亚洲| 久久国产精品久久久久久久久久| 欧美精品手机在线| 国产精品一区二区三区毛片淫片| 色婷婷综合久久久久中文字幕1| 亚洲精品中文字幕女同| 日韩中文视频免费在线观看| 欧美午夜视频一区二区| 成人av色在线观看| 久久亚洲精品一区二区| 欧美小视频在线观看| 亚洲黄色av网站| 黑人巨大精品欧美一区免费视频| 国产精品美女www爽爽爽视频| 久久久精品免费| 日韩av在线免播放器| 成人做爽爽免费视频| 青草青草久热精品视频在线网站| 亚洲综合中文字幕在线| 九九久久久久99精品| 色诱女教师一区二区三区| 日韩视频在线免费观看| 国产精品视频一区二区高潮| 青草成人免费视频| 久久精品视频99| 亚洲综合在线做性| 欧美黑人一级爽快片淫片高清| 91热福利电影| 国产美女91呻吟求| 国产亚洲a∨片在线观看| 国产欧美日韩最新| 97超级碰碰碰久久久| 97超级碰碰碰| 91在线观看免费高清完整版在线观看| 日韩美女在线观看| 日韩av一区在线观看| 国产91精品黑色丝袜高跟鞋| 成人精品一区二区三区电影免费| 欧美日韩国产专区| 欧美在线视频在线播放完整版免费观看| 午夜精品久久久久久99热软件| 欧美激情精品久久久| 尤物精品国产第一福利三区| 欧美理论电影在线观看| 国产一区二区三区直播精品电影| 国产一区二区激情| 午夜精品在线视频| 欧美激情啊啊啊| 日韩三级成人av网| 57pao成人国产永久免费| 91精品国产综合久久久久久蜜臀| 91精品国产91久久久久久| 亚洲国产一区自拍| 日本sm极度另类视频| 日韩欧美黄色动漫| 国产丝袜一区二区三区| 国产精品视频最多的网站| 欧美专区在线观看| 亚洲成年人在线| 中文字幕日韩精品在线| 国产精品久久久久久网站| 亚洲性夜色噜噜噜7777| 亚洲综合色av| 91久久久久久久一区二区| 美女av一区二区三区| 2019中文字幕免费视频| 亚洲国产美女久久久久| 一本色道久久88精品综合| 成年无码av片在线| 欧美精品在线网站| 国模精品视频一区二区三区| 亚洲a级在线观看| 色先锋资源久久综合5566| 亚洲精品中文字幕av| 亚洲国产精品成人精品| 国产综合视频在线观看| 国产精品永久在线| 日韩亚洲第一页| 国产综合在线看| 欧美另类69精品久久久久9999| 亚洲va欧美va国产综合剧情| 中文字幕欧美国内| 国产mv久久久| 久久视频国产精品免费视频在线| 久久这里只有精品99| 日韩在线中文字幕| 国产视频在线观看一区二区| 国产精品免费小视频| 九九热这里只有精品6| 亚洲综合在线播放| 久久久久久久一区二区三区| www.日本久久久久com.| 国产精品久久久久久超碰| 日韩电影免费观看在线观看| 亚洲аv电影天堂网| 国产精品久久一| 日本精品一区二区三区在线播放视频| 国产成人一区三区| 国产精品女人网站| 国产精品69精品一区二区三区| 日韩精品中文在线观看| 精品久久久久久久久久国产| 亚洲精品狠狠操| 久久精品视频一| 国产91精品久久久久| 久久精品99无色码中文字幕| 日本久久久a级免费| 91精品免费视频| 日本欧美黄网站| 国产日韩欧美在线看| 蜜臀久久99精品久久久久久宅男| 一本色道久久综合狠狠躁篇的优点| 亚洲精品在线看| 亚洲成人av在线播放| 中文字幕国产亚洲2019| 一区二区三区回区在观看免费视频| 日韩亚洲欧美成人| 国产免费一区二区三区在线观看| 欧美亚洲日本网站| 亚洲人成自拍网站| 欧美午夜丰满在线18影院| 成人免费视频网| 欧美精品久久久久久久久久| 欧美日韩第一页| 韩国精品美女www爽爽爽视频| 欧美在线观看www| 欧美日韩国产精品一区二区不卡中文| 国产福利精品av综合导导航| 亚洲综合av影视| 奇米4444一区二区三区| 欧美性猛交xxxx黑人猛交| 国产精品免费视频久久久| 亚洲影院高清在线| 国产精品久久久久久久美男| 亚洲欧美激情精品一区二区| 精品中文字幕久久久久久| 欧美日韩激情小视频| 国产亚洲人成网站在线观看| 97在线观看免费| 欧美精品在线播放| 亚洲人a成www在线影院| 久久久久久久久久久av| 国产一区深夜福利| xxxx欧美18另类的高清| 久久影视电视剧免费网站| 亚洲电影免费观看高清完整版在线| 国产精品99久久久久久www| 日韩精品免费在线视频观看| 亚洲色图35p| 欧美日韩一区二区在线播放| 欧美高清一级大片| 欧美在线中文字幕| 欧美大奶子在线| 日韩高清电影免费观看完整版| 色偷偷av亚洲男人的天堂| 亚洲欧洲在线看| 日韩精品视频免费在线观看|