青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

C++ Programmer's Cookbook

{C++ 基礎} {C++ 高級} {C#界面,C++核心算法} {設計模式} {C#基礎}

STL----string

今天看stl中的string得:

一  問題:

舉例來說,如果文本格式是:用戶名 電話號碼,文件名name.txt

Tom 23245332
Jenny 22231231
Heny 22183942
Tom 23245332
...
現(xiàn)在我們需要對用戶名排序,且只輸出不同的姓名。
-------------------------------

如果使用C/C++ 就麻煩了,他需要做以下工作:

  1. 先打開文件,檢測文件是否打開,如果失敗,則退出。
  2. 聲明一個足夠大得二維字符數(shù)組或者一個字符指針數(shù)組
  3. 讀入一行到字符空間
  4. 然后分析一行的結構,找到空格,存入字符數(shù)組中。
  5. 關閉文件
  6. 寫一個排序函數(shù),或者使用寫一個比較函數(shù),使用qsort排序
  7. 遍歷數(shù)組,比較是否有相同的,如果有,則要刪除,copy...
  8. 輸出信息

-------------------------------------
我們可以使用 fstream來代替麻煩的fopen fread fclose, 用vector 來代替數(shù)組。最重要的是用 string來代替char * 數(shù)組,使用sort排序算法來排序,用unique 函數(shù)來去重。聽起來好像很不錯 smile 。看看下面代碼(例程1):

#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
#include <fstream>
using namespace std;
int main(){
        ifstream in("name.txt");
        string strtmp;
        vector<string> vect;
        while(getline(in, strtmp, '\n'))
        vect.push_back(strtmp.substr(0, strtmp.find(' ')));
        sort(vect.begin(), vect.end());
        vector<string>::iterator it=unique(vect.begin(), vect.end());
        copy(vect.begin(), it, ostream_iterator<string>(cout, "\n"));
        return 0;
}
--------------------------------------------





string 函數(shù)列表
函數(shù)名 描述
begin 得到指向字符串開頭的Iterator
end 得到指向字符串結尾的Iterator
rbegin 得到指向反向字符串開頭的Iterator
rend 得到指向反向字符串結尾的Iterator
size 得到字符串的大小
length 和size函數(shù)功能相同
max_size 字符串可能的最大大小
capacity 在不重新分配內(nèi)存的情況下,字符串可能的大小
empty 判斷是否為空
operator[] 取第幾個元素,相當于數(shù)組
c_str 取得C風格的const char* 字符串
data 取得字符串內(nèi)容地址
operator= 賦值操作符
reserve 預留空間
swap 交換函數(shù)
insert 插入字符
append 追加字符
push_back 追加字符
operator+= += 操作符
erase 刪除字符串
clear 清空字符容器中所有內(nèi)容
resize 重新分配空間
assign 和賦值操作符一樣
replace 替代
copy 字符串到空間
find 查找
rfind 反向查找
find_first_of 查找包含子串中的任何字符,返回第一個位置
find_first_not_of 查找不包含子串中的任何字符,返回第一個位置
find_last_of 查找包含子串中的任何字符,返回最后一個位置
find_last_not_of 查找不包含子串中的任何字符,返回最后一個位置
substr 得到字串
compare 比較字符串
operator+ 字符串鏈接
operator== 判斷是否相等
operator!= 判斷是否不等于
operator< 判斷是否小于
operator>> 從輸入流中讀入字符串
operator<< 字符串寫入輸出流
getline 從輸入流中讀入一行


------------------------------------
三 string提供了三個函數(shù)滿足其要求:
const charT* c_str() const 
const charT* data() const 
size_type copy(charT* buf, size_type n, size_type pos = 0) const 
其中: 
  1. c_str 直接返回一個以\0結尾的字符串。
  2. data 直接以數(shù)組方式返回string的內(nèi)容,其大小為size()的返回值,結尾并沒有\(zhòng)0字符。
  3. copy 把string的內(nèi)容拷貝到buf空間中。

---------------------
四    basic_string 是基于字符序列容器(Sequence)的模板類, 包含了說有序列容器的常用操作,同時也包含了字符串的標準操作,如"查找"和"合并" 。
typedef basic_string <char> string;
typedef basic_string<wchar_t> wstring;

五  Extended STL string

ext_string,提供一些常用的功能,例如:

  1. 定義分隔符。給定分隔符,把string分為幾個字段。
  2. 提供替換功能。例如,用winter, 替換字符串中的wende
  3. 大小寫處理。例如,忽略大小寫比較,轉(zhuǎn)換等
  4. 整形轉(zhuǎn)換。例如把"123"字符串轉(zhuǎn)換為123數(shù)字。

附錄:ext_string:


/**
 * @mainpage Extended STL string
 * @author Keenan Tims - ktims@gotroot.ca
 * @version 0.2
 * @date 2005-04-17
 * @section desc Description
 * ext_string aims to provide a portable, bug-free implementation of many useful extensions to the
 * standard STL string class.  These extensions are commonly available among higher-level languages
 * such as Perl and Python, but C++ programmers are generally left on their own when it comes to
 * basic string processing.  By extending the STL's string, we can provide a drop-in replacement for STL
 * strings with the greater functionality of higher-level languages.
 *
 * The primary goal of this library is to make the STL string class more usable to programmers that
 * are doing simple string manipulation on a small scale.  Due to the usability goals of this class,
 * many actions will be inefficiently implemented for the sake of ease of use.  Some of this is
 * mitigated somewhat by doing modification in-place, however many unnecessary copies of data are
 * created by some methods, and the vector-returning methods are inefficient in that they copy the
 * substrings into the vector, then return a copy of the vector.  This would be much more efficient
 * as an iterator model.
 *
 *
 * @section feat Features
 *
 * @li Fully based on the STL, ext_string provides a superset of std::string methods
 * @li String splitting (tokenizing), on a character, a string, or whitespace
 * @li Replacement of substrings or characters with another string or character
 * @li String case operations (check, adjust)
 * @li Integer conversion
 * @li Fully open-source under a BSD-like license for use in any product
 *
 * @if web
 * @section download Downloads
 *
 * Downloads are provided in tar.gz and zip formats containing this documentation, the header file,
 * and the library's changelog.  The latest version of ext_string is 0.2, released on April 17,
 * 2005.
 *
 * @li<a href="files/ext_string-0.2.tar.gz">ext_string-0.2.tar.gz</a>
 * @li<a href="files/ext_string-0.2.zip">ext_string-0.2.zip</a>
 * @li <small><a href="files/ext_string-0.1.tar.gz">ext_string-0.1.tar.gz</a></small>
 * @li <small><a href="files/ext_string-0.1.zip">ext_string-0.1.zip</a></small>
 *
 * @section changelog Changelog
 *
 * The changelog is viewable online <a href="files/CHANGELOG">here</a>
 *
 * @endif
 *
 * @section notes Notes/Limitations
 * @li Copying all the substrings into a vector for the substring methods is pretty inefficient,
 * both for space and time.  It would be more prudent to model an iterator to split the string based
 * on the specified parameters, but this is more difficult to implement and more cumbersome to use.
 * Performance is not the main goal of this library, usability is, thus the tradeoff is deemed to be
 * acceptable.
 * @li References are not used too aptly in this class.  Some performance tuning could be done to
 * minimize unnecessary data copying.
 * @li The basic methods of std::string aren't overridden by this class, thus assigning the return
 * value of eg. string::insert() to an ext_string instance will make an unnecessary string object
 * which is then copy-constructed to an ext_string (I believe, internal workings of inheritance and
 * polymorphism in C++ are somewhat beyond my experience).  These methods should be wrapped by
 * ext_string to return the proper type.
 *
 *
 * @section related Related Documentation
 *
 * @li SGI's STL string reference: http://www.sgi.com/tech/stl/basic_string.html
 *
 *
 * @section license License
 *
 * Copyright (c) 2005, Keenan Tims
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
 * @li Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer.
 * @li Redistributions in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or other materials provided with
 * the distribution.
 * @li Neither the name of the Extended STL String project nor the names of its contributors may be used to endorse
 * or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 */

#ifndef _EXT_STRING_H
#define _EXT_STRING_H

#include <string>
#include <vector>

namespace std
{

 /**
  * An extension of STL's string providing additional functionality that is often availiable in
  * higher-level languages such as Python.
  */
 class ext_string : public string
 {
  public:
   /**
    * Default constructor
    *
    * Constructs an empty ext_string ("")
    */
   ext_string() : string() { }

   /**
    * Duplicate the STL string copy constructor
    *
    * @param[in] s   The string to copy
    * @param[in] pos The starting position in the string to copy from
    * @param[in] n   The number of characters to copy
    */
   ext_string(const string &s, size_type pos = 0, size_type n = npos) : string(s, pos, npos) { }

   /**
    * Construct an ext_string from a null-terminated character array
    *
    * @param[in] s The character array to copy into the new string
    */
   ext_string(const value_type *s) : string(s) { }

   /**
    * Construct an ext_string from a character array and a length
    *
    * @param[in] s The character array to copy into the new string
    * @param[in] n The number of characters to copy
    */
   ext_string(const value_type *s, size_type n) : string(s, n) { }

   /**
    * Create an ext_string with @p n copies of @p c
    *
    * @param[in] n The number of copies
    * @param[in] c The character to copy @p n times
    */
   ext_string(size_type n, value_type c) : string(n, c) { }

   /**
    * Create a string from a range
    *
    * @param[in] first The first element to copy in
    * @param[in] last  The last element to copy in
    */
   template <class InputIterator>
    ext_string(InputIterator first, InputIterator last) : string(first, last) { }

   /**
    * The destructor
    */
   ~ext_string() { }

   /**
    * Split a string by whitespace
    *
    * @return A vector of strings, each of which is a substring of the string
    */
   vector<ext_string> split(size_type limit = npos) const
   {
    vector<ext_string> v;

    const_iterator
     i = begin(),
       last = i;
    for (; i != end(); i++)
    {
     if (*i == ' ' || *i == '\n' || *i == '\t' || *i == '\r')
     {
      if (i + 1 != end() && (i[1] == ' ' || i[1] == '\n' || i[1] == '\t' || i[1] == '\r'))
       continue;
      v.push_back(ext_string(last, i));
      last = i + 1;
      if (v.size() >= limit - 1)
      {
       v.push_back(ext_string(last, end()));
       return v;
      }
     }
    }

    if (last != i)
     v.push_back(ext_string(last, i));

    return v;
   }

   /**
    * Split a string by a character
    *
    * Returns a vector of ext_strings, each of which is a substring of the string formed by splitting
    * it on boundaries formed by the character @p separator.  If @p limit is set, the returned vector
    * will contain a maximum of @p limit elements with the last element containing the rest of
    * the string.
    *
    * If @p separator is not found in the string, a single element will be returned in the vector
    * containing the entire string.
    *
    * The separators are removed from the output
    *
    * @param[in] separator The character separator to split the string on
    * @param[in] limit     The maximum number of output elements
    * @return A vector of strings, each of which is a substring of the string
    *
    * @section split_ex Example
    * @code
    * std::ext_string s("This|is|a|test.");
    * std::vector<std::ext_string> v = s.split('|');
    * std::copy(v.begin(), v.end(), std::ostream_iterator<std::ext_string>(std::cout, "\n"));
    *
    * This
    * is
    * a
    * test.
    * @endcode
    */
   vector<ext_string> split(value_type separator, size_type limit = npos) const
   {
    vector<ext_string> v;

    const_iterator
     i = begin(),
     last = i;
    for (; i != end(); i++)
    {
     if (*i == separator)
     {
      v.push_back(ext_string(last, i));
      last = i + 1;
      if (v.size() >= limit - 1)
      {
       v.push_back(ext_string(last, end()));
       return v;
      }
     }
    }

    if (last != i)
     v.push_back(ext_string(last, i));

    return v;
   }

   /**
    * Split a string by another string
    *
    * Returns a vector of ext_strings, each of which is a substring of the string formed by
    * splitting it on boundaries formed by the string @p separator.  If @p limit is set, the
    * returned vector will contain a maximum of @p limit elements with the last element
    * containing the rest of the string.
    *
    * If @p separator is not found in the string, a single element will be returned in the
    * vector containing the entire string.
    *
    * The separators are removed from the output
    *
    * @param[in] separator The string separator to split the string on
    * @param[in] limit     The maximum number of output elements
    * @return A vector of strings, each of which is a substring of the string
    *
    * @ref split_ex
    */
   vector<ext_string> split(const string &separator, size_type limit = npos) const
   {
    vector<ext_string> v;

    const_iterator
     i = begin(),
     last = i;
    for (; i != end(); i++)
    {
     if (string(i, i + separator.length()) == separator)
     {
      v.push_back(ext_string(last, i));
      last = i + separator.length();

      if (v.size() >= limit - 1)
      {
       v.push_back(ext_string(last, end()));
       return v;
      }
     }
    }

    if (last != i)
     v.push_back(ext_string(last, i));

    return v;
   }

   /**
    * Convert a string into an integer
    *
    * Convert the initial portion of a string into a signed integer.  Once a non-numeric
    * character is reached, the remainder of @p string is ignored and the integer that was
    * read returned.
    *
    * @param s The string to convert
    * @return The integer converted from @p string
    */
   static long int integer(const string &s)
   {
    long int retval = 0;
    bool neg = false;

    for (const_iterator i = s.begin(); i != s.end(); i++)
    {
     if (i == s.begin())
     {
      if (*i == '-')
      {
       neg = true;
       continue;
      }
      else if (*i == '+')
       continue;
     }
     if (*i >= '0' && *i <= '9')
     {
      retval *= 10;
      retval += *i - '0';
     }
     else
      break;
    }

    if (neg)
     retval *= -1;

    return retval;
   }

   /**
    * Convert the string to an integer
    *
    * Convert the initial portion of the string into a signed integer.  Once a non-numeric
    * character is reached, the remainder of the string is ignored and the integer that had
    * been read thus far is returned.
    *
    * @return The integer converted from the string
    */
   long int integer() const
   {
    return integer(*this);
   }

   /**
    * Split a string into chunks of size @p chunklen.  Returns a vector of strings.
    *
    * Splits a string into chunks of the given size.  The final chunk may not fill its
    * entire allocated number of characters.
    *
    * @param[in] chunklen The number of characters per chunk
    * @return A vector of strings, each of length <= chunklen
    *
    * @section chunk_split-ex Example
    * @code
    * std::ext_string s("abcdefghijk");
    * std::vector<std::ext_string> v = s.chunk_split(3);
    * std::copy(v.begin(), v.end(), ostream_iterator<std::ext_string>(cout, " "));
    *
    * abc def ghi jk
    * @endcode
    */
   vector<ext_string> chunk_split(size_type chunklen) const
   {
    vector<ext_string> retval;
    retval.reserve(size() / chunklen + 1);

    size_type count = 0;
    const_iterator
     i = begin(),
     last = i;
    for (; i != end(); i++, count++)
    {
     if (count == chunklen)
     {
      count = 0;
      retval.push_back(ext_string(last, i));
      last = i;
     }
    }
    
    if (last != i)
     retval.push_back(ext_string(last, i));

    return retval;
   }

   /**
    * Join a sequence of strings by some glue to create a new string
    *
    * Glue is not added to the end of the string.
    *
    * @pre [first, last) is a valid range
    * @pre InputIterator is a model of STL's Input Iterator
    * @pre InputIterator must point to a string type (std::string, std::ext_string, char *)
    *
    * @param[in] glue  The glue to join strings with
    * @param[in] first The beginning of the range to join
    * @param[in] last  The end of the range to join
    * @return A string constructed of each element of the range connected together with @p glue
    *
    * @section join_ex Example
    * @code
    * std::vector<std::ext_string> v;
    * v.push_back("This");
    * v.push_back("is");
    * v.push_back("a");
    * v.push_back("test.");
    * std::cout << std::ext_string::join("|", v.begin(), v.end()) << std::endl;
    *
    * This|is|a|test.
    * @endcode
    */
   template <class InputIterator>
    static ext_string join(const string &glue, InputIterator first, InputIterator last)
    {
     ext_string retval;

     for (; first != last; first++)
     {
      retval.append(*first);
      retval.append(glue);
     }
     retval.erase(retval.length() - glue.length());

     return retval;
    }

   /**
    * Join a sequence of strings by some glue to create a new string
    *
    * @copydoc join
    * @ref join_ex
    */
   template <class InputIterator>
    static ext_string join(value_type glue, InputIterator first, InputIterator last)
    {
     ext_string retval;

     for (; first != last; first++)
     {
      retval.append(*first);
      retval.append(1, glue);
     }
     retval.erase(retval.length() - 1);

     return retval;
    }

   /**
    * Search for any instances of @p needle and replace them with @p s
    *
    * @param[in] needle The string to replace
    * @param[in] s      The replacement string
    * @return    *this
    * @post     All instances of @p needle in the string are replaced with @p s
    *
    * @section replace-ex Example
    * @code
    * std::ext_string s("This is a test.");
    * s.replace("is", "ere");
    * std::cout << s << std::endl;
    *
    * There ere a test.
    * @endcode
    */
   ext_string &replace(const string &needle, const string &s)
   {
    size_type
     lastpos = 0,
     thispos;

    while ((thispos = find(needle, lastpos)) != npos)
    {
     string::replace(thispos, needle.length(), s);
     lastpos = thispos + 1;
    }
    return *this;
   }

   /**
    * Search of any instances of @p needle and replace them with @p c
    *
    * @param[in] needle The character to replace
    * @param[in] c      The replacement character
    * @return           *this
    * @post             All instances of @p needle in the string are replaced with @p c
    *
    * @ref replace-ex
    */
   ext_string &replace(value_type needle, value_type c)
   {
    for (iterator i = begin(); i != end(); i++)
     if (*i == needle)
      *i = c;

    return *this;
   }

   /**
    * Repeat a string @p n times
    *
    * @param[in] n The number of times to repeat the string
    * @return ext_string containing @p n copies of the string
    *
    * @section repeat-ex Example
    * @code
    * std::ext_string s("123");
    * s = s * 3;
    * std::cout << s << std::endl;
    *
    * 123123123
    * @endcode
    */
   ext_string operator*(size_type n)
   {
    ext_string retval;
    for (size_type i = 0; i < n; i++)
     retval.append(*this);

    return retval;
   }

   /**
    * Convert the string to lowercase
    *
    * @return *this
    * @post The string is converted to lowercase
    */
   ext_string &tolower()
   {
    for (iterator i = begin(); i != end(); i++)
     if (*i >= 'A' && *i <= 'Z')
      *i = (*i) + ('a' - 'A');
    return *this;
   }

   /**
    * Convert the string to uppercase
    *
    * @return *this
    * @post The string is converted to uppercase
    */
   ext_string &toupper()
   {
    for (iterator i = begin(); i != end(); i++)
     if (*i >= 'a' && *i <= 'z')
      *i = (*i) - ('a' - 'A');
    return *this;
   }

   /**
    * Count the occurances of @p str in the string.
    *
    * @return The count of substrings @p str in the string
    */
   size_type count(const string &str) const
   {
    size_type
     count = 0,
     last = 0,
     cur = 0;

    while ((cur = find(str, last + 1)) != npos)
    {
     count++;
     last = cur;
    }

    return count;
   }

   /**
    * Determine if the string is alphanumeric
    *
    * @return true if the string contains only characters between a-z, A-Z and 0-9 and
    * contains at least one character, else false
    */
   bool is_alnum() const
   {
    if (length() == 0)
     return false;

    for (const_iterator i = begin(); i != end(); i++)
    {
     if (*i < 'A' || *i > 'Z')
      if (*i < '0' || *i > '9')
       if (*i < 'a' || *i > 'z')
        return false;
    }

    return true;
   }

   /**
    * Determine if the string is alphabetic only
    *
    * @return true of the string contains only characters between a-z and A-Z and contains at
    * least one character, else false
    */
   bool is_alpha() const
   {
    if (length() == 0)
     return false;

    for (const_iterator i = begin(); i != end(); i++)
     if (*i < 'A' || (*i > 'Z' && (*i < 'a' || *i > 'z')))
      return false;

    return true;
   }

   /**
    * Determine if the string is numeric only
    *
    * @return true if the string contains only characters between 0-9 and contains at least
    * one character, else false
    */
   bool is_numeric() const
   {
    if (length() == 0)
     return false;

    for (const_iterator i = begin(); i != end(); i++)
     if (*i < '0' || *i > '9')
      return false;

    return true;
   }

   /**
    * Determine if a string is all lower case
    *
    * @return true if there is at least one character, and all characters are lowercase
    * letters, else false
    */
   bool is_lower() const
   {
    if (length() == 0)
     return false;

    for (const_iterator i = begin(); i != end(); i++)
     if (*i < 'a' || *i < 'z')
      return false;

    return true;
   }

   /**
    * Determine if a string is all upper case
    *
    * @return true if there is at least one character, and all characters are uppercase
    * letters, else false
    */
   bool is_upper() const
   {
    if (length() == 0)
     return false;

    for (const_iterator i = begin(); i != end(); i++)
     if (*i < 'A' || *i > 'Z')
      return false;

    return true;
   }

   /**
    * Swap the case of a string
    *
    * @post Converts all uppercase to lowercase, and all lowercase to uppercase in the string
    * @return *this
    */
   ext_string &swapcase()
   {
    for (iterator i = begin(); i != end(); i++)
     if (*i >= 'A' && *i <= 'Z')
      *i += ('a' - 'A');
     else if (*i >= 'a' && *i <= 'z')
      *i -= ('a' - 'A');
    
    return *this;
   }
 };
}
#endif
也可以找到 http://www.gotroot.ca/ext_string/

posted on 2005-12-13 16:25 夢在天涯 閱讀(5691) 評論(1)  編輯 收藏 引用 所屬分類: STL/Boost

評論

# re: STL----string 2009-09-16 11:21 egmkang.wang

std::string::data()
結尾不一定有'\0'吧.
c_str是肯定有.

我自己實踐的結果是,data()也會返回'\0'結尾的const char*.
如果data()不返回,那么程序可能就會有問題.......  回復  更多評論   

公告

EMail:itech001#126.com

導航

統(tǒng)計

  • 隨筆 - 461
  • 文章 - 4
  • 評論 - 746
  • 引用 - 0

常用鏈接

隨筆分類

隨筆檔案

收藏夾

Blogs

c#(csharp)

C++(cpp)

Enlish

Forums(bbs)

My self

Often go

Useful Webs

Xml/Uml/html

搜索

  •  

積分與排名

  • 積分 - 1815003
  • 排名 - 5

最新評論

閱讀排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
      <noscript id="pjuwb"></noscript>
            <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
              <dd id="pjuwb"></dd>
              <abbr id="pjuwb"></abbr>
              亚洲一区999| 久久精品电影| 国产精品普通话对白| 亚洲第一在线视频| 国产精品亚洲аv天堂网| 亚洲少妇一区| 亚洲高清不卡av| 亚洲第一福利在线观看| 欧美第一黄网免费网站| 亚洲人成人77777线观看| 亚洲三级电影在线观看| 亚洲性xxxx| 久久精品视频va| 农夫在线精品视频免费观看| 日韩视频永久免费观看| 亚洲精品影院| 亚洲一区二区综合| 在线播放中文字幕一区| 亚洲狠狠丁香婷婷综合久久久| 欧美日韩综合视频网址| 欧美在线关看| 亚洲欧洲三级| 久久精品在线观看| 9色精品在线| 亚洲午夜免费福利视频| 久久久91精品国产| 亚洲成色999久久网站| 9久草视频在线视频精品| 亚洲欧美另类国产| 欧美成人激情在线| 久久久久久久久久久久久久一区 | 黄色免费成人| 亚洲精品社区| 欧美在线观看一二区| 久久美女艺术照精彩视频福利播放| 国产欧美日韩精品专区| 久久精品国产亚洲一区二区三区| 久久精品国产一区二区三区免费看| 欧美极品aⅴ影院| 久久久一二三| 亚洲一区黄色| 国产精品99久久不卡二区| 亚洲国产精品久久久久秋霞影院| 久久综合伊人77777| 一本一本久久a久久精品综合妖精 一本一本久久a久久精品综合麻豆 | 亚洲一区二区精品在线| 免费不卡在线视频| 午夜在线视频一区二区区别| 销魂美女一区二区三区视频在线| 老司机午夜精品视频| 裸体一区二区| 免费黄网站欧美| 国产一区二区三区久久| 亚洲图片在线| 亚洲日韩欧美视频| 嫩模写真一区二区三区三州| 极品少妇一区二区三区| 性色一区二区| 久久久久成人精品| 亚洲一区二区三区久久 | 国产婷婷成人久久av免费高清 | 亚洲自拍16p| 亚洲精品一区二区三区蜜桃久| 亚洲黄色三级| 一区二区亚洲精品| 极品尤物一区二区三区| 精品动漫3d一区二区三区免费| 一区二区三区成人精品| 亚洲欧美在线一区二区| 久久成人免费视频| 99精品欧美一区二区三区综合在线| 欧美成人国产| 一区二区三区 在线观看视频 | 99视频在线精品国自产拍免费观看| 亚洲激情在线| 一区二区欧美日韩| 欧美日韩一区二区精品| 亚洲一区二区在线观看视频| 午夜免费久久久久| 西瓜成人精品人成网站| 国语自产精品视频在线看抢先版结局| 亚洲国产婷婷| 国产精品久久久久77777| 久久久久久久精| 国模套图日韩精品一区二区| 久久久久中文| 亚洲高清一区二区三区| 免费毛片一区二区三区久久久| 亚洲高清久久| 欧美一区二区三区久久精品| 午夜视频在线观看一区二区| 欧美人妖在线观看| 国产视频一区在线| 久久嫩草精品久久久精品一| 亚洲视频在线观看一区| 国产精品网站视频| 免费不卡视频| 国产精品成人播放| 久久香蕉国产线看观看av| 欧美激情第10页| 欧美亚洲免费电影| 欧美成人dvd在线视频| 欧美一区二区三区成人| 欧美激情按摩在线| 亚洲人成在线观看网站高清| 欧美一区二区在线看| 久久国产黑丝| 国产综合色一区二区三区| 这里只有精品视频| 欧美一区二区三区的| 国产精品一区二区三区久久| 免费中文字幕日韩欧美| 欧美在线电影| 一区二区三区视频免费在线观看| 亚洲成人在线免费| 亚洲第一区在线观看| 亚洲一级黄色片| 亚洲欧洲免费视频| 欧美资源在线观看| 亚洲欧美日韩成人| 欧美日韩一区二区三区四区在线观看| 极品尤物av久久免费看| 久久精品亚洲精品国产欧美kt∨| 在线视频日韩| 亚洲精品偷拍| 久久久一区二区| 久久精品日韩欧美| 国产精品久久久久天堂| 亚洲欧洲午夜| 日韩午夜黄色| 一区二区欧美在线观看| 欧美午夜在线视频| 欧美激情精品久久久久久大尺度| 看欧美日韩国产| 亚洲欧洲精品一区二区三区不卡 | 蜜臀91精品一区二区三区| 国产日产亚洲精品| 亚洲欧美三级伦理| 久久精品99| 欧美成人综合在线| 久久亚洲二区| 免费成人黄色| 99国内精品久久久久久久软件| 亚洲国产高清视频| 亚洲第一精品夜夜躁人人躁| 91久久在线视频| 国产精品久久久久国产a级| 亚洲精品国产精品乱码不99按摩| 国产精品第2页| 亚洲视频免费观看| 曰本成人黄色| 久久综合九色99| 午夜影院日韩| 国产精品视频你懂的| 女同性一区二区三区人了人一| 韩国精品在线观看| 久久一二三四| 亚洲精品久久久久| 午夜精品福利在线| 女人天堂亚洲aⅴ在线观看| 亚洲第一区色| 亚洲一区二三| 国产在线视频欧美一区二区三区| 久久久久久国产精品mv| 亚洲精品欧美专区| 欧美一区二区三区四区在线观看地址| 久久精品日韩一区二区三区| 另类成人小视频在线| 日韩一级黄色大片| 欧美在线综合| 亚洲第一色中文字幕| 亚洲四色影视在线观看| 国产午夜精品一区二区三区视频 | 最新亚洲视频| 国内成+人亚洲| 一本久道久久综合中文字幕| 欧美一区二区三区免费视| 国产综合网站| 欧美区在线播放| 亚洲国产欧美国产综合一区| 一卡二卡3卡四卡高清精品视频| 国产精品视频九色porn| 亚洲精品中文字幕在线| 欧美一级久久久| 欧美午夜精品久久久| 久久精品一区蜜桃臀影院 | 久久久久久亚洲精品中文字幕| 亚洲在线电影| 激情小说另类小说亚洲欧美| 亚洲欧美日产图| 亚洲夜间福利| 在线免费观看一区二区三区| 香蕉视频成人在线观看| 欧美在线播放| 亚洲精品中文字幕女同| 在线播放亚洲| 久久久久久久精| 亚洲无线观看| 亚洲美女av黄| 亚洲高清电影|