日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++读取读取csv、xls文件的类

發布時間:2023/12/16 c/c++ 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++读取读取csv、xls文件的类 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

由于經常要讀取大量的數據進行分析,自己封裝了一個C++的類,代替網上的rapidcsv庫。一切以自己的需求為準,夠用簡略就好。真正體會到了C++程序員造輪子的樂趣。自己的拼裝車就是好用。
文章需要的csv、xls數據文件,大家可以自己從網上下載:
1、網易財經頻道可以下載到csv格式的股票日線數據,可以試著用我的quickcsv庫讀取
2、同花順股票軟件也可以導出xls格式的excel文件,也可以用我的庫來讀取。
所以,本文就不附加下載內容了,自己找材料測試
今天廢話真多,好了,上代碼:
QuickCsv.h頭文件

#pragma once #ifndef QUICKCSV_H #define QUICKCSV_H #include<vector> #include<iostream> #include <fstream> #include <sstream> #include<assert.h>using namespace std;class QuickCsv { public://QuickCsv(std::string Path):mPath(Path)//{// ReadCsvData(mPath);//}QuickCsv(){}~QuickCsv(){VectorCsvOfAllLines.clear();}/*初始化數據,現在使用初始化函數可以保證一個類對象實例可以調用不同的市場數據*/void InitData(std::string Path){mPath = Path;VectorCsvOfAllLines.clear();//mPath.assign(Path); //文件路徑決定了計算哪個市場的數據//定義為私有函數、放在構造函數里面,更有面向對象編程的意味:實例化一個類對象,就對應一個csv文件的處理ReadCsvData(Path);}/*寫入一行csv文件Mode(方式) 意義"r" 打開一個用于讀取的文本文件"w" 創建一個用于寫入的文本文件"a" 附加到一個文本文件"rb" 打開一個用于讀取的二進制文件"wb" 創建一個用于寫入的二進制文件"ab" 附加到一個二進制文件"r+" 打開一個用于讀/寫的文本文件"w+" 創建一個用于讀/寫的文本文件"a+" 打開一個用于讀/寫的文本文件"rb+" 打開一個用于讀/寫的二進制文件"wb+" 創建一個用于讀/寫的二進制文件"ab+" 打開一個用于讀/寫的二進制文件*/void WriteInDataToCsv(std::string Path, std::string VectorDataLine, const char* Mode)//寫csv文件,保存文件{FILE* mFile;fopen_s(&mFile, Path.c_str(), Mode);if (!mFile){printf_s("文件不存在,打開失敗!!!");return;}fprintf_s(mFile, VectorDataLine.c_str());fflush(mFile);fclose(mFile);}/*重載,寫入一行csv文件*/void WriteInDataToCsv(std::string Path, std::vector<std::string>VectorDataLine, const char* Mode)//寫csv文件,保存文件{FILE* mFile;fopen_s(&mFile, Path.c_str(), Mode);if (!mFile){printf_s("文件不存在,打開失敗!!!");return;}for (auto itr = VectorDataLine.begin(); itr != VectorDataLine.end(); ++itr){if (itr == VectorDataLine.end() - 1){fprintf_s(mFile, "%s\0", itr->c_str());fflush(mFile);}else{fprintf_s(mFile, "%s\t", itr->c_str());fflush(mFile);}}fclose(mFile);}/*重載,寫入多行csv文件*/void WriteInDataToCsv(std::string Path, std::vector<std::vector<std::string>>VectorDataLine, const char* Mode)//寫csv文件,保存文件{FILE* mFile;fopen_s(&mFile, Path.c_str(), Mode);if (!mFile){printf_s("文件不存在,打開失敗!!!");return;}for (auto itr = VectorDataLine.begin(); itr != VectorDataLine.end(); ++itr){//從itr->begin()到itr->end()是一系列string類型的數據(一行)for (auto data_itr = itr->begin(); data_itr != itr->end(); ++data_itr){if (data_itr == itr->end() - 1){fprintf_s(mFile, "%s\0", data_itr->c_str());fflush(mFile);}else{fprintf_s(mFile, "%s\t", data_itr->c_str());fflush(mFile);}}}fclose(mFile);}void DeletRow(int RowID)//刪除行{//(一)先操作內存數據for (int i = 0; i < VectorCsvOfAllLines.size(); i++){if (i == RowID)//要刪除的行,忽略掉{continue;}TmpVectorCsvOfAllLines.push_back(VectorCsvOfAllLines.at(i));//其余的內容保留在臨時的vector里面}VectorCsvOfAllLines.swap(TmpVectorCsvOfAllLines); //用臨時的vector交換原來的VectorCsvOfAllLines數據,實現修改的目的TmpVectorCsvOfAllLines.clear(); //清空臨時的vector//(2)接下來寫入本地文件WriteInDataToCsv(mPath, VectorCsvOfAllLines, "w");}void DeleteColumn(int ColumnID)//刪除列{std::vector<std::string>tmpLine;//臨時的行//(一)先操作內存數據for (auto itr = VectorCsvOfAllLines.begin(); itr!= VectorCsvOfAllLines.end(); ++itr){int num = 0;for (auto lineitr = itr->begin(); lineitr != itr->end();++lineitr)//itr就是每一行數據,遍歷每一行{if (num == ColumnID)//如果遇到我們要刪除的列,跳過{continue;}else//否則就把每一行不準備刪除的數據保留在tmpLine里面{tmpLine.push_back(*lineitr);}num++;}TmpVectorCsvOfAllLines.push_back(tmpLine);//其余的內容保留在臨時的vector里面tmpLine.clear();//每次循環處理一行數據,用完清理一次}VectorCsvOfAllLines.swap(TmpVectorCsvOfAllLines); //用臨時的vector交換原來的VectorCsvOfAllLines數據,實現修改的目的TmpVectorCsvOfAllLines.clear(); //清空臨時的vector//(2)接下來寫入本地文件WriteInDataToCsv(mPath, VectorCsvOfAllLines, "w");}void InsertRow(int RowID,std::vector<std::string>myLine)//插入行{//(1)先操作內存數據std::vector<std::vector<std::string>>::iterator myitr;//找到第RowID行的迭代器int num = 0;for (auto itr = VectorCsvOfAllLines.begin(); itr != VectorCsvOfAllLines.end(); ++itr){if (num == RowID){myitr = itr --;//num++是前一次循環break;}else{num++;}}VectorCsvOfAllLines.insert(myitr, myLine);//(2)接下來寫入本地文件WriteInDataToCsv(mPath, VectorCsvOfAllLines, "w");}void InsertColumn(int ColumnID,std::vector<std::string>myColumData)//插入列{std::vector<std::string>tmpLine;//臨時的行//(1)先操作內存數據int RowID = 0;for (auto itr = VectorCsvOfAllLines.begin(); itr != VectorCsvOfAllLines.end(); ++itr){RowID++;tmpLine = *itr;//把一行的數據保存在臨時行里面std::vector<std::string>::iterator myitr= GetIteratorByID(ColumnID, tmpLine);//找到每一行第ColumnID列的迭代器if (RowID < myColumData.size()){tmpLine.insert(myitr, myColumData.at(RowID));//此處有風險:有可能使用者給的列數據myColumData不夠多,導致內存溢出TmpVectorCsvOfAllLines.push_back(tmpLine);//其余的內容保留在臨時的vector里面}tmpLine.clear();//每次循環處理一行數據,用完清理一次}VectorCsvOfAllLines.swap(TmpVectorCsvOfAllLines); //用臨時的vector交換原來的VectorCsvOfAllLines數據,實現修改的目的TmpVectorCsvOfAllLines.clear(); //清空臨時的vector//(2)接下來寫入本地文件WriteInDataToCsv(mPath, VectorCsvOfAllLines, "w");}/*功能:獲取第ColumID列的所有內容,比如股票代碼、名稱、換手率等等也可以獲取所有的行名稱,即所謂第0列參數:int ColumID: 列的序號bool GetHeader: 為真,保留列頭(第0行);為假,只保留數據,沒有表頭項*/std::vector<std::string> GetColumStrings(int ColumID, bool GetHeader){std::vector<std::string> VectorCsvRowNames;//保存行名稱數據std::string tmpStr;for (auto itr = VectorCsvOfAllLines.begin(); itr != VectorCsvOfAllLines.end(); ++itr){tmpStr = itr->at(ColumID);//tmpStr.erase(0, 2);VectorCsvRowNames.push_back(tmpStr);tmpStr.clear();}if (!GetHeader){VectorCsvRowNames.erase(VectorCsvRowNames.begin());}return VectorCsvRowNames;}/*功能:同時獲取若干列的所有內容,比如同時獲取股票代碼、名稱、換手率、市盈率等等,方便以后提取數據參數:int ColumID: 列的序號bool GetHeader: 為真,保留列頭(第0行);為假,只保留數據,沒有表頭項*/std::vector<std::vector<std::string>> GetColumsStrings(std::vector<int> ColumIDs, bool GetHeader){std::vector<std::vector<std::string>> VectorCsvRowNames;//保存行名稱數據if (VectorCsvOfAllLines.size() == 0){std::cout << "類內部GetColumsStrings函數調用時VectorCsvOfAllLines沒有數據:" << std::endl;return VectorCsvRowNames;//空的,剛剛定義的}std::vector<std::string>oneLine;for (auto itr = VectorCsvOfAllLines.begin(); itr != VectorCsvOfAllLines.end(); ++itr)//一大行數據{for (size_t i = 0; i < ColumIDs.size(); i++)//生成的一小行數據0、1、4、8{//cout << "itr->at(*int_itr)=" << itr->at(*int_itr) << "\n" << endl;//itr代表VectorCsvOfAllLines中的一行數據,這是一個vector;//現在只按照ColumIDs提取*int_itr這幾項:itr->at(0)、itr->at(3)、itr->at(4)、itr->at(8)等等oneLine.push_back(itr->at(ColumIDs[i]));//把提取出來的這幾項放入oneLine組成新的一行數據}VectorCsvRowNames.push_back(oneLine);//把新生成的一行數據oneLine放入VectorCsvRowNamesoneLine.clear();}if (!GetHeader){VectorCsvRowNames.erase(VectorCsvRowNames.begin());}return VectorCsvRowNames;}//獲取csv文件數據的列表表頭,std::vector<std::string> GetHeaders()//讀取和處理一行csv數據{//vector<std::string>VectorCsvHeader;//ifstream inFile(mPath.c_str(), ios::in); //聲明一個ifstream對象,與文件名關聯mPath已經構造函數傳參//string HeaderLineStr;//getline(inFile, HeaderLineStr);//不放在while循環里只讀取第一行,csv文件的數據表頭//istringstream sin(HeaderLineStr); //將整行字符串lineStr讀入到字符串流istringstream中//string headerDatas;把字符串行HeaderLineStr按照字符“,”分割為每一“行”(實際上就是數據塊)每一個數據塊(字符“,"分割的)放入headerDatas//while (getline(sin, headerDatas, mch))//{// VectorCsvHeader.push_back(Trim(headerDatas));// headerDatas.clear();//}//HeaderLineStr.clear();//return VectorCsvHeader;return VectorCsvOfAllLines.at(0);}/*功能:獲取第RowID行的數據參數:int RowID: 行的序號bool IsRowName: 為真,有行名稱;(行的第0項為行名稱,不是要計算、比較的數據)為假,無行名稱(行的第0項為直接是數據,比如服務器得到的API數據,自己需要按照約定規則的處理),只保留數據bool IsHeader 為真,存在列頭(第0行不是數據);為假,第0行直接是數據,只保留數據,沒有表頭項是否存在表頭有的數據列表沒有標頭,第0行直接是數據,比如服務器得到的API數據,自己需要按照約定規則的處理*/std::vector<double>GetRowData(int RowID, bool IsRowName, bool IsHeader){if (IsHeader)//為真,存在列頭(第0行不是數據);{RowID += 1;}//需要判斷RowID是否為第0行,有的數據列表沒有標頭,第0行直接是數據,比如服務器得到的API數據,自己需要按照約定規則的處理std::vector<double> VectorCsvRowDatas;//保存行數據std::vector<std::string> VectormyLine = VectorCsvOfAllLines.at(RowID);//得到第RowID行if (IsRowName)//為真,有行名稱;(行的第0項為行名稱,不是要計算、比較的數據){for (auto itr = VectormyLine.begin() + 1; itr != VectormyLine.end(); ++itr){VectorCsvRowDatas.push_back(StringToDouble(*itr));//printf_s("%s\n",itr->at(0).c_str());}}else//為假,無行名稱(行的第0項直接就是數據,比如服務器得到的API數據,自己需要按照約定規則的處理){for (auto itr = VectormyLine.begin(); itr != VectormyLine.end(); ++itr){VectorCsvRowDatas.push_back(StringToDouble(*itr));//printf_s("%s\n",itr->at(0).c_str());}}return VectorCsvRowDatas;}/*功能:(函數重載)獲取第RowID行的數據參數:int RowID: 行的序號bool IsRowName: 為真,有行名稱;(行的第0項為行名稱,不是要計算、比較的數據)為假,無行名稱(行的第0項為直接是數據,比如服務器得到的API數據,自己需要按照約定規則的處理),只保留數據bool IsHeader 為真,存在列頭(第0行不是數據);為假,第0行直接是數據,只保留數據,沒有表頭項是否存在表頭有的數據列表沒有標頭,第0行直接是數據,比如服務器得到的API數據,自己需要按照約定規則的處理*/std::vector<double>GetRowData(int RowID, std::vector<int>ColumsID, bool IsHeader){if (IsHeader)//為真,存在列頭(第0行不是數據);{RowID += 1;}//需要判斷RowID是否為第0行,有的數據列表沒有標頭,第0行直接是數據,比如服務器得到的API數據,自己需要按照約定規則的處理std::vector<double> VectorCsvRowDatas;//保存行數據std::vector<std::string> VectormyLine = VectorCsvOfAllLines.at(RowID);//得到第RowID行for (auto int_itr = ColumsID.begin(); int_itr != ColumsID.end(); ++int_itr){//cout <<"看看 *int_itr的值:"<< * int_itr << endl;VectorCsvRowDatas.push_back(StringToDouble(VectormyLine[*int_itr]));}return VectorCsvRowDatas;} private:/*從MyVector里面獲取第DataID項的迭代器*/std::vector<std::string>::iterator GetIteratorByID(int DataID, std::vector<std::string>MyVector)//找到每一行第ColumnID列的迭代器{std::vector<std::string>::iterator myitr;//找到每一行第ColumnID列的迭代器int num = 0;for (auto lineitr = MyVector.begin(); lineitr != MyVector.end(); ++lineitr)//tmpLine就是每一行數據,遍歷每一行{if (num == DataID)//如果遇到我們要添加的列,記錄下來迭代器{myitr = lineitr;break;}else//否則就跳過{num++;}}return myitr;}//定義為私有函數、放在構造函數里面,更有面向對象編程的意味:實例化一個類對象,就對應一個csv文件的處理void ReadCsvData(std::string Path)//讀取csv文件{FILE* mFile;fopen_s(&mFile, Path.c_str(), "r");if (!mFile){printf_s("文件%s不存在、或者文件名、文件路徑有誤,文件打開失敗!!!\n", Path.c_str());return;}fclose(mFile);/*getline()函數用于輸入流,讀取字符到buffer中,直到下列情況發生:num - 1個字符已經讀入,碰到一個換行標志,碰到一個EOF,或者,任意地讀入,直到讀到字符delim。delim字符不會被放入buffer中。*/std::ifstream fin(Path.c_str()); //打開文件流操作,構造函數傳參std::string line;getline(fin, line);//先判斷是什么類型的數據文件if (line.find(',') != std::string::npos)//存在分隔符“,”{VectorCsvOfAllLines.push_back(ParseLineStringToVector(line, ','));//別把文件中的第一行給忘掉了//把mPath文件按行整行讀取,讀取到行line當中,這個行是我們人類所理解的行,以換行符“\n”結束。//遇到文件尾標志eof終止讀取,結束while循環while (getline(fin, line)){//csv文件某一行數據項std::vector<std::string> VectorCsvDataOfOneLine = ParseLineStringToVector(line, ',');VectorCsvOfAllLines.push_back(VectorCsvDataOfOneLine);VectorCsvDataOfOneLine.clear();//strtod函數也可以實現string到double的轉換}}else if (line.find('\t') != std::string::npos)//存在空格“tab”為分隔符{VectorCsvOfAllLines.push_back(ParseLineStringToVector(line, '\t'));//別把文件中的第一行給忘掉了//把mPath文件按行整行讀取,讀取到行line當中,這個行是我們人類所理解的行,以換行符“\n”結束。//遇到文件尾標志eof終止讀取,結束while循環while (getline(fin, line)){//csv文件某一行數據項std::vector<std::string> VectorCsvDataOfOneLine = ParseLineStringToVector(line, '\t');VectorCsvOfAllLines.push_back(VectorCsvDataOfOneLine);VectorCsvDataOfOneLine.clear();//strtod函數也可以實現string到double的轉換}}else//既不存在“,”也不存在“\t”符{while (getline(fin, line)){//csv文件某一行數據項std::vector<std::string> VectorCsvDataOfOneLine;VectorCsvDataOfOneLine.push_back(line);VectorCsvOfAllLines.push_back(VectorCsvDataOfOneLine);VectorCsvDataOfOneLine.clear();//strtod函數也可以實現string到double的轉換}}//看看結果//cout << "ReadCsvData函數運算結束,VectorCsvOfAllLines里面有:"<< VectorCsvOfAllLines.size()<<"行數據\n" << endl;}//按照某個特殊的字符ch切割每一行數據,放在vector<std::string> 里面std::vector<std::string> ParseLineStringToVector(std::string LineStr, char ch){std::istringstream sin(LineStr); //將整行字符串line讀入到字符串流istringstream中std::string StrOfOneLine;std::vector<std::string> VectorLineStr;//csv文件某一行數據項//sin(line)是從文件中讀取的一行的數據(回車結束的自然行);//StrOfOneLine是從sin(line)中讀取一行一行的數據(實際上是數據塊),每“行”以字符“,"為分隔符;//每“行”字符串(數據塊)StrOfOneLine又放入vector當中。while (getline(sin, StrOfOneLine, ch)){VectorLineStr.push_back(Trim(StrOfOneLine)); //將剛剛讀取的每一行的數據塊字符串添加到vector中LineStr.clear();//看看是否有必要}return VectorLineStr;//strtod函數也可以實現string到double的轉換}//整理數據std::string Trim(std::string& str){str.find_first_not_of(" \t\r\n");// 在字符串str中從索引0開始,返回首次不匹配"\t\r\n"的位置str.erase(0, str.find_first_not_of(" \t\r\n"));str.erase(str.find_last_not_of(" \t\r\n") + 1);return str;}/*C++實現atof()--string to double的轉化*/double StringToDouble(std::string str){assert(str.size() != NULL);//斷言非常重要,發現bug//if(str.size() == NULL);//斷言非常重要,發現bug//{// str = "00";//}int i = 0;double dou_num = 0;double t = 10;bool fh_ = false;if (str[i] == '-'){fh_ = true;i++;}while (str[i] != '\0')//不是換行符,數據結束符{if (str[i] == '.')//找到小數點就移位到下一個字符{i++;//移位到下一個字符break;}dou_num = dou_num * 10 + str[i] - '0';i++;}while (str[i] != '\0'){dou_num = dou_num + ((double)str[i] - '0') / t;t *= 10;i++;}if (fh_)return -1.0 * dou_num;elsereturn dou_num;} private://對于修改操作必須把結果寫入本地文件,所以必須要保存文件名和文件路徑std::string mPath;//csv文件的路徑,初始化函數傳參std::vector<std::vector<std::string>> VectorCsvOfAllLines;//所有的行,包括列表表頭、行名稱std::vector<std::vector<std::string>> TmpVectorCsvOfAllLines;//修改數據時需要的臨時變量;所有的行,包括列表表頭、行名稱int ColumnNum = 0;//csv文件數據的列數,根據表頭計算出來 };#endif // !QUICKCSV_H

調用QuickCsv類的cpp文件

#include"QuickCsv.h" QuickCsv qc("../shanghai_a.xls"); //QuickCsv qc("../DaLian.csv");int main() {//調用GetRowNames()函數//vector<std::string> VectorCsvRowNames=qc.GetColumStrings(0,1);//參數為真,把列的表頭一項也加進來//int i = 0;//for (auto itr = VectorCsvRowNames.begin(); itr != VectorCsvRowNames.end(); ++itr)//{// printf_s("滬市有%d只股票,第%d只股票代碼:%s\n", VectorCsvRowNames.size(), i, itr->c_str());// i++;//}//VectorCsvRowNames.clear();//調用GetRowData()函數(一)int RowNum =6;//vector<double>mRow = qc.GetRowData(RowNum, 1, 1);//第0行的數據//for (auto itr = mRow.begin(); itr != mRow.end(); ++itr)//{// printf_s("調用GetRowData()函數(一):第%d行有%d項數據:%.5f\n", RowNum, mRow.size(), *itr);//}//mRow.clear();調用GetRowData()函數(二)重載//vector<int> myColumsID = {3,4, 5 };//我只獲取第RowNum行--第2、3、4、5列的數據//vector<double>mRow2 = qc.GetRowData(RowNum, myColumsID, 1);//第0行的數據//for (auto itr = mRow2.begin(); itr != mRow2.end(); ++itr)//{// printf_s("重載調用GetRowData()函數:第%d行有%d項數據:%.5f\n", RowNum, mRow2.size(), *itr);//}//mRow2.clear(); //先進后出//myColumsID.clear(); //先進后出//調用GetHeaders()函數//vector<std::string>VectorCsvHeader=qc.GetHeaders();//看看效果://int i = 0;//for (auto itr = VectorCsvHeader.begin(); itr != VectorCsvHeader.end(); ++itr)//{// printf_s("csv文件有%d列;第%d列表頭:%s\n", VectorCsvHeader.size(), i, itr->c_str());// i++;//}//VectorCsvHeader.clear();vector<int>myColums = { 0,1,4,7 };//代碼、名稱、換手率、流通比vector<vector<string>> myVector=qc.GetColumsStrings(myColums,1);int i = 0;for (auto itr = myVector.begin(); itr != myVector.end(); ++itr){if (i > 50)break;//通過itr得到了每一個數據行for (auto mitr = itr->begin(); mitr != itr->end(); ++mitr){if (mitr != itr->end() - 1){printf_s("%s---", mitr->c_str());}else{printf_s("%s\n", mitr->c_str());}}i++;}myColums.clear();//先進后出myVector.clear();//先進后出getchar();qc.~QuickCsv();return 0; }

效果圖:

總結

以上是生活随笔為你收集整理的C++读取读取csv、xls文件的类的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 激情五月综合色婷婷一区二区 | 2022国产精品 | 成人性生交大片免费看中文 | 日韩欧美午夜 | 亚洲电影在线看 | 美女被猛网站 | 亚洲精品一区二区三区在线观看 | 奇米影视在线视频 | 97se视频| 国产高清免费在线 | 婷婷五月综合缴情在线视频 | 欧美日韩一区在线 | 麻豆传媒网 | 中文字幕日韩在线观看 | 高清一区二区三区四区五区 | 日本大尺度电影免费观看全集中文版 | 可以免费观看av的网站 | 69免费视频 | 亚洲一区二区三区欧美 | 国产av不卡一区 | 在线岛国 | 成年黄色片 | 特级毛片a | 午夜精品久久久久久久四虎美女版 | 成人免费影视网站 | 欧美日韩亚洲精品内裤 | 亚洲色图 一区二区 | kendra lust free xxx | 美日韩丰满少妇在线观看 | 国产精品久久久av | 日本免费专区 | 69人妻一区二区三区 | 成年人黄色免费视频 | 国产成人午夜精品 | 天天摸夜夜爽 | 韩国一区二区视频 | 青草超碰 | av电影一区二区三区 | 操www | 日韩激情小视频 | 视频二区在线观看 | 亚洲男人天堂2022 | 久久毛片 | 欧美精品在线一区 | 国产午夜伦鲁鲁 | 国产女大学生av | 亚洲最新av网站 | 免费美女毛片 | 少妇在线播放 | 亚洲精品国产欧美在线观看 | 国产91在线观看丝袜 | 国产白浆视频 | 久久久久久久综合 | 免费无码毛片一区二区app | 综合色网站 | 人人妻人人澡人人爽精品日本 | 最好看的2018中文2019 | 天天操天天玩 | 中文字幕在线看片 | 男人天堂新地址 | 一级爱爱免费视频 | 偷拍亚洲色图 | 中文字幕电影一区二区 | av美女在线 | 清纯唯美第一页 | 亚洲男人的天堂网站 | 日本在线精品 | 国产亚洲一区二区三区 | 伊人69| 欧洲亚洲成人 | 日韩在线网址 | 99艹| 91丨九色丨黑人外教 | 青青草综合在线 | 国产精品91在线观看 | 日韩中文在线播放 | 免费黄色av网址 | 丝袜一区二区三区 | 黄色一级大片在线免费看国产 | 日韩在线中文 | 无码人妻精品一区二区蜜桃视频 | 国产三级高清 | 日韩成人中文字幕 | 黄色片视频在线观看 | 国产高清精品一区 | 一级美女视频 | 成人国产精品入口免费视频 | 99精品久久久久久久婷婷 | 国产丝袜在线视频 | 国产一线二线三线女 | 亚洲av人人澡人人爽人人夜夜 | 99久久黄色| 男女激情在线观看 | 国产无遮挡裸体免费视频 | 国产精品入口日韩视频大尺度 | 亚洲综合五月天婷婷丁香 | 日本加勒比一区二区 | 亚洲综合小说网 | 中文字幕一区二区久久人妻 |