中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

常州市城鄉(xiāng)建設(shè)學(xué)院網(wǎng)站如何在百度推廣自己的產(chǎn)品

常州市城鄉(xiāng)建設(shè)學(xué)院網(wǎng)站,如何在百度推廣自己的產(chǎn)品,網(wǎng)站 建設(shè)標(biāo)準(zhǔn),網(wǎng)站建設(shè)與網(wǎng)站開發(fā)目錄 1、基本成員變量 2、默認(rèn)成員函數(shù) 構(gòu)造函數(shù) 析構(gòu)函數(shù) 拷貝構(gòu)造函數(shù)(深拷貝) 賦值運算符重載 3、容量與大小相關(guān)的函數(shù) size capacity 4、字符串訪問相關(guān)函數(shù) operator [ ]重載 迭代器 5、增加的相關(guān)函數(shù) reserve擴容 resize push_back追加字符 appe…

目錄

1、基本成員變量

2、默認(rèn)成員函數(shù)

構(gòu)造函數(shù)

析構(gòu)函數(shù)

拷貝構(gòu)造函數(shù)(深拷貝)

賦值運算符重載?

3、容量與大小相關(guān)的函數(shù)

size

capacity?

4、字符串訪問相關(guān)函數(shù)

operator [ ]重載

迭代器?

5、增加的相關(guān)函數(shù)?

reserve擴容

resize?

push_back追加字符

append追加字符串

operator+=?

insert?

6、刪除的相關(guān)函數(shù)

erase

clear清除數(shù)據(jù)

7、查找的相關(guān)函數(shù)

find

8、c_str獲取字符串

9、swap交換函數(shù)

10、非成員函數(shù)

關(guān)系運算符函數(shù)重載

<<流插入運算符重載

>>流提取運算符重載

getline函數(shù)

整型和字符串之間的轉(zhuǎn)換函數(shù)


1、基本成員變量

namespace Fan
{//使用命名空間防止我們實現(xiàn)的string與庫里的string沖突class string{public://......private:char* _str;      //存儲字符串size_t _size;    //有效字符的個數(shù)size_t _capacity; //實際存儲的有效字符的個數(shù),不包含'\0'const static size_t npos;};const size_t string::npos = -1;
}

2、默認(rèn)成員函數(shù)

構(gòu)造函數(shù)

這里的構(gòu)造函數(shù)我們最好寫成全缺省函數(shù),與庫里面的構(gòu)造函數(shù)相一致。

//全缺省的默認(rèn)構(gòu)造函數(shù)
string(const char* str = "") //標(biāo)準(zhǔn)庫里string定義對象的默認(rèn)值為空串""//按聲明的順序進(jìn)行初始化:_size(strlen(str)), _capacity(_size)
{_str = new char[_capacity + 1]; //在堆上為_str開辟空間,+1是給'\0'預(yù)留的strcpy(_str, str); //把常量字符串的內(nèi)容拷貝過去
}

析構(gòu)函數(shù)

string類里面的_str成員指向的空間是在堆區(qū),堆區(qū)的空間不能自動銷毀,因此需要我們手動去進(jìn)行銷毀。

//析構(gòu)函數(shù)
~string()
{if (_str){delete[] _str;_str = nullptr;_size = _capacity = 0;}
}

拷貝構(gòu)造函數(shù)(深拷貝)

首先我們不寫時編譯器會默認(rèn)生成一個拷貝構(gòu)造函數(shù),不過是值拷貝或者淺拷貝,是按照字節(jié)拷貝的。

編譯器默認(rèn)生成的拷貝構(gòu)造函數(shù)是淺拷貝,淺拷貝針對日期類是非常合適的,但是像string類這樣_str是動態(tài)開辟在堆上的。如果我們使用值拷貝會導(dǎo)致:1、同一塊空間會析構(gòu)兩次。2、一個對象修改會影響另外一個。因此我們需要進(jìn)行深拷貝。深拷貝的核心要點在于我和你有一樣的值,但是使用的不是同一塊空間。

深拷貝有兩種寫法:傳統(tǒng)寫法和現(xiàn)代寫法。

  • 1、傳統(tǒng)寫法:

?傳統(tǒng)寫法就是先開辟一塊能夠容納原字符串大小的空間,最后把拷貝的對象的字符串?dāng)?shù)據(jù)拷貝到新開的空間里面。

//拷貝構(gòu)造函數(shù)
//不能用淺拷貝,原因如下:1、析構(gòu)兩次 2、一個對象修改會影響另外一個
// 傳統(tǒng)寫法
string(const string& s):_size(strlen(s._str)), _capacity(_size)
{_str = new char[_capacity + 1];strcpy(_str, s._str);
}
  • 2、現(xiàn)代寫法:

傳統(tǒng)寫法是自己開空間然后拷貝數(shù)據(jù),而現(xiàn)代寫法就是創(chuàng)建中間變量。比如我們拿s1作為參數(shù)去拷貝構(gòu)造s2,我們創(chuàng)建一個對象tmp,然后拿s1._str的字符串作為參數(shù)給tmp對象完成構(gòu)造。然后再利用swap函數(shù)把tmp對象的_str、_size、_capacity全部與s2的交換即可完成現(xiàn)代方法的深拷貝。不過需要注意的是我們需要把s2的數(shù)據(jù)置空,避免交換后tmp調(diào)用析構(gòu)函數(shù)會出現(xiàn)析構(gòu)隨機值的錯誤現(xiàn)象。

//現(xiàn)代方法
string(const string& s):_str(nullptr), _size(0), _capacity(0)
{string tmp(s._str); swap(tmp);
}

賦值運算符重載?

  • 思路:

如果我們把s3賦值給s1,這里并不能直接進(jìn)行賦值,我們需要考慮兩個問題。

  1. 如果我s1的空間小于s3,那么直接拷貝過去會導(dǎo)致越界
  2. 如果我s1的空間遠(yuǎn)大于s3的空間,直接拷貝過去就會導(dǎo)致空間的過度浪費。只有在我s1和s3的空間差不多大的時候,才可以直接進(jìn)行拷貝。

綜上:我們先把s1原先指向的內(nèi)容delete掉,然后再重新開辟一個和s3一樣大的空間,需要注意的是記得多開一個字節(jié),因為還有'\0'字符。我們再利用strcpy把s3的內(nèi)容拷貝給s1即可。

?優(yōu)化點:

  1. 要避免自己給自己賦值,如若自己給自己賦值,我們直接返回。所以要加上if條件判斷
  2. 如果我new失敗那么就會導(dǎo)致拋異常,而先前我依舊釋放了s1,此時就把s1給破壞了。為了避免這一點,我們可以先開空間再拷貝數(shù)據(jù)最后釋放從而進(jìn)行優(yōu)化。
  • 1、傳統(tǒng)寫法:
//賦值運算符重載--> 深拷貝
//s1=s3 s1.operator=(&s1,s3);
string& operator=(const string& s)
{//防止自己給自己賦值if (this != &s){/*//法一//先刪除原先s1的所有空間,防止賦值后s1過大導(dǎo)致空間浪費,s1過小導(dǎo)致空間不夠delete[] _str;//給s1開辟與s3等價空間大小,要多開一字節(jié)給'\0'_str = new char[strlen(s._str) + 1];strcpy(_str, s._str);*///法二優(yōu)化//先開辟空間char* tmp = new char[s._capacity + 1];strcpy(tmp, s._str);delete[] _str;_str = tmp;_size = s._size;_capacity = s._capacity;}return *this;
}
  • 2、現(xiàn)代寫法:

這里的現(xiàn)代寫法與上文拷貝構(gòu)造的現(xiàn)代方法沒有什么區(qū)別。

//現(xiàn)代寫法
string& operator=(const string& s)
{if (this != &s){string tmp(s._str);swap(tmp);}return *this;
}

還有一種更加簡潔的現(xiàn)代方法,上述寫法是引用傳參,這里我們可以直接傳值傳參,讓編譯器自動調(diào)用拷貝構(gòu)造函數(shù),再把拷貝出來的對象作為右值與左值進(jìn)行交換。

//法二:簡潔版string& operator=(string s) //傳值傳參調(diào)用拷貝構(gòu)造,s就是s3的深拷貝{swap(s); //交換這兩個對象return *this;}

簡潔版本的弊端就在于無法避免自己給自己賦值,但很少會出現(xiàn)自己給自己賦值的行為。


3、容量與大小相關(guān)的函數(shù)

size

直接返回隱含this指針指向的_size即為字符串長度

//返回字符串的長度
size_t size() const //不改變內(nèi)部成員,最好加上const
{return _size;
}

capacity?

?直接返回隱含this指針指向的_capacity即可

//返回字符串容量
size_t capacity() const //不改變內(nèi)部成員,最好加上const
{return _capacity;
}

4、字符串訪問相關(guān)函數(shù)

operator [ ]重載

有了operator[ ]運算符重載,我們就可以直接用下標(biāo)+[ ]進(jìn)行元素訪問,不過這里我們還需要提供一個const版本的operator[ ]運算符重載以便于普通對象和const對象均可以調(diào)用而不會出現(xiàn)權(quán)限方法的問題。

//版本1
char& operator[](size_t pos) //引用返回,便于后續(xù)修改返回的字符
{assert(pos < _size); //確保pos位置的合法性,不能超過字符串return _str[pos]; //返回pos位置字符的引用
}
//版本2
const char& operator[](size_t pos)const
{assert(pos < _size);return _str[pos];
}

迭代器?

string類的迭代器我們可以將其理解為字符指針

  • begin函數(shù)的作用就是返回字符串中的第一個字符的地址
  • end函數(shù)的作用就是返回字符串最后一個字符的后一個位置地址,即'\0'的地址
//版本1
typedef char* iterator;
iterator begin()
{return _str; //返回第一個有效字符的指針
}
iterator end()
{return _str + _size; //返回最后一個字符后一個位置的地址,即'\0'的地址
}

和上文的operator[ ]重載一樣,我們也需要寫一個const版本的迭代器,以便于后續(xù)的const對象也能夠調(diào)用。

//版本2:只讀,const對象可調(diào)用
typedef const char* const_iterator;
const_iterator begin()const
{return _str; //返回第一個有效字符的指針
}
const_iterator end()const
{return _str + _size; //返回最后一個字符后一個位置的地址,即'\0'的地址
}

還有一種基于迭代器的遍歷方式:范圍for

范圍for的底層實現(xiàn)原理和迭代器沒兩樣,只不過看著比較高級。

void test_string()
{Fan::string s1("hello world");//迭代器Fan::string::iterator it = s1.begin();while (it != s1.end()){cout << *it << " "; //h e l l o  w o r l dit++;}cout << endl;//范圍forfor (auto& ch : s1) //加上引用,相當(dāng)于是每個字符的別名,便于修改{ch -= 1;}for (auto& ch : s1){cout << ch << " "; }
}

為了驗證范圍for是基于迭代器的,我們把模擬迭代器的代碼注釋掉我們再看下結(jié)果:

我們可以看到當(dāng)我們把模擬迭代器的代碼注釋掉以后范圍for也不起作用了。?


5、增加的相關(guān)函數(shù)?

reserve擴容

reserve擴容只影響_capacity空間,不影響_size,其有以下兩點規(guī)則

  1. 當(dāng)n大于對象當(dāng)前的capacity時,將capacity擴大到n或者大于n。
  2. 當(dāng)n小于對象當(dāng)前的capacity時,無需操作。
//reserve擴容
void reserve(size_t n)
{if (n > _capacity){char* tmp = new char[n + 1]; //每次開空間一定要多給一個字節(jié)給'\0'strcpy(tmp, _str);//釋放舊空間delete[] _str;//把新空間賦給_str_str = tmp;//更新容量_capacity_capacity = n;}
}

resize?

resize是將字符串調(diào)整為n個字符的長度,不僅會改變_size大小,還會改變_capacity的大小。規(guī)則如下:

  1. 如果n小于當(dāng)前的_size長度,將_size縮小到n
  2. 如果n大于當(dāng)前的_size長度,將_size擴大到n,擴大的字符默認(rèn)為'\0'

//resize調(diào)整大小
void resize(size_t n, char ch = '\0')
{//如果n<_size,就保留前n個字符即可,把下標(biāo)n置為'\0'if (n < _size){_size = n;_str[_size] = '\0';}else{//如果n>_capacity,就要擴容if (n > _capacity){reserve(n);}for (size_t i = _size; i < n; i++){//把剩余的字符置為ch_str[i] = ch;}_size = n;_str[_size] = '\0';}
}

push_back追加字符

?首先我們要考慮需不需要擴容,如果需要,我們直接復(fù)用reserve函數(shù)進(jìn)行增容,追加字符以后我們要把最后一個下標(biāo)_size對應(yīng)的值置為'\0'。

//push_back
void push_back(char ch)
{//法一//先檢查是否需要擴容if (_size == _capacity){//復(fù)用reserve進(jìn)行擴容,如果一開始容量為0,記得處理,因為容量*2依舊為0reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = ch;_size++;_str[_size] = '\0'; //注意最后一個值恒為'\0'以確保字符串的完整性
}

這里我們還可以使用后文寫好的insert尾插字符,因為當(dāng)insert函數(shù)中的pos為_size時即為尾插:

//push_back尾插字符
void push_back(char ch)
{//法二:復(fù)用insert尾插入字符insert(_size, ch);
}

append追加字符串

使用append追加字符串首先要做的就是判斷是否需要擴容,擴容后利用strcpy函數(shù)把追加的字符串拷貝到原字符串末尾即可,這里不需要額外處理'\0',因為strcpy默認(rèn)把'\0'拷貝過去。

//append
void append(const char* str)
{//統(tǒng)計追加字符串后的長度size_t len = _size + strlen(str);//判斷是否需要擴容if (len > _capacity){reserve(len);}//把字符串追加到末尾strcpy(_str + _size, str);_size = len;
}

我們這里也可以使用后文的insert追加字符串來完成,因為當(dāng)pos為_size時,就是在尾部追加字符串。

void append(const char* str)
{//法二:復(fù)用insert函數(shù)insert(_size, str);
}

operator+=?

operator+=可以追加字符、字符串、對象等。

  • 追加字符:直接復(fù)用push_back
//operator+=字符
string& operator+=(char ch)
{//復(fù)用push_backpush_back(ch);return *this;
}
  • 追加字符串:直接復(fù)用append
//operator+=字符串
string& operator+=(const char* str)
{//復(fù)用appendappend(str);return *this;
}

insert?

insert的作用是在指定pos位置往后插入字符或者字符串。

  • insert在pos位置插入字符

這里我們首先要判斷pos的合法性,然后再進(jìn)行挪動數(shù)據(jù)。我們從'\0'位置的下一個位置(_size+1)開始往前挪動。因此定義end指向'\0'后一個位置,當(dāng)end挪到與pos位置重合時停止,最后把插入的字符ch挪到下標(biāo)pos處。最后更新_size++。

//insert插入字符
string& insert(size_t pos, char ch)
{assert(pos <= _size);if (_size == _capacity){//復(fù)用reserve進(jìn)行擴容,如果一開始容量為0,記得處理。否則容量*2依舊為0reserve(_capacity == 0 ? 4 : _capacity * 2);}//依次挪動size_t end = _size + 1;while (end > pos){_str[end] = _str[end - 1];end--;}//當(dāng)end挪動到pos的位置時停止挪動,并把ch賦值到pos的下標(biāo)處_str[pos] = ch;_size += 1;return *this;
}

?測試如下:

void test_string()
{Fan::string s("hello world");s.insert(6, '#');s += '#';cout << s.c_str() << endl; //hello #world#for (auto& ch : s){cout << ch << " ";}cout << "$" << endl; //h e l l o  # w o r l d # $s += '\0';for (auto& ch : s){cout << ch << " ";}cout << "$" << endl; //h e l l o  # w o r l d #  $s.insert(0, '#');cout << s.c_str() << endl;//#hello #world#
}
  • insert在pos位置插入字符串

我們首先判斷是否需要擴容,接下來挪動數(shù)據(jù)。定義變量end為_size+len的位置,把pos處往后的字符串整體往后挪動直至空出插入字符串的空間。然后再利用strncpy函數(shù)把插入的字符串拷貝過去。

//insert插入字符串
string& insert(size_t pos, const char* str)
{assert(pos <= _size);size_t len = strlen(str);if (len == 0){//如果傳進(jìn)來的字符串為空,直接返回即可return *this;}if (_size + len > _capacity){//判斷是否擴容reserve(_size + len);}size_t end = _size + len;//當(dāng)end>=pos+len時都不結(jié)束循環(huán)while (end >= pos + len){_str[end] = _str[end - len];end--;}//不能使用strcpy,因為會把\0也拷進(jìn)去,就會出錯strncpy(_str + pos, str, len);_size += len;return *this;
}

?測試如下:

void test_string()
{Fan::string s("hello world");s.insert(0, "xxx");cout << s.c_str() << endl; //xxxhello world
}

6、刪除的相關(guān)函數(shù)

erase

如果給定刪除的長度len為npos無符號值,或者說len+pos的長度>=_size,那么我們可以直接把pos位置的值設(shè)定為'\0'即可,因為此時就是把pos后的數(shù)據(jù)全部刪除。除了此種特殊情況,其余的就是從pos+len處開始往前挪動直到_size+1為止。pos后的數(shù)據(jù)往前覆蓋即可。

//erase刪除
void erase(size_t pos, size_t len = npos)
{assert(pos < _size);if (len == npos || pos + len >= _size){//此種情況是直接刪除pos后的所有數(shù)據(jù),直接把pos處設(shè)定為'\0'即可_str[pos] = '\0';_size = pos;}else{size_t begin = pos + len;while (begin <= _size){_str[begin - len] = _str[begin];begin++;}_size -= len;}
}

測試如下:

void test_string()
{Fan::string s("hello world");s.insert(0, "xxx");cout << s.c_str() << endl; //xxxhello worlds.erase(0, 3);cout << s.c_str() << endl; //hello world
}

clear清除數(shù)據(jù)

clear函數(shù)是用來清除原字符串的所有數(shù)據(jù),但其空間仍保留。所以我們只需要把下標(biāo)0的位置置為'\0',并把有效字符個數(shù)_size置為0即可。

//clear清除數(shù)據(jù)
void clear()
{_str[0] = '\0';_size = 0;
}

7、查找的相關(guān)函數(shù)

find

find函數(shù)分為查找字符字符串

  • find查找字符:

我們直接進(jìn)行遍歷即可:

//find查找字符:
size_t find(char ch, size_t pos = 0)
{for (; pos < _size; pos++){if (_str[pos] == ch)return pos;}//沒有找到就返回npos,-1return npos; //-1
}
  • find查找字符串:

這里我們可以直接復(fù)用C語言的strstr函數(shù)進(jìn)行查找,不過該函數(shù)返回的是地址,我們想要獲得下標(biāo)直接利用地址相減即可。

//find查找字符串:
size_t find(const char* str, size_t pos = 0)
{//直接復(fù)用C語言函數(shù)strstr即可,strstr函數(shù)返回的是地址const char* p = strstr(_str + pos, str); if (p == nullptr){return npos;}else{//返回下標(biāo)直接用p-str即可return p - _str;}
}

8、c_str獲取字符串

?c_str用于獲取C類型的字符串,直接返回字符串首地址。

//c_str 獲取C形式的字符串
const char* c_str()const //最好加上const,便于普通對象和const對象均可調(diào)用
{return _str;
}

9、swap交換函數(shù)

swap函數(shù)用于交換兩個對象的數(shù)據(jù),我們可以通過復(fù)用庫里面的swap函數(shù)來完成,但是要在前面加上作用域限定符"::"。讓編譯器在全局域的庫里調(diào)用swap函數(shù)。

//swap交換函數(shù)
void swap(string& s)
{std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);
}

10、非成員函數(shù)

關(guān)系運算符函數(shù)重載

關(guān)系運算符有==、!=、<、<=、>、>=這6類,我們在先前的日期類中已經(jīng)講過類似的。這里的關(guān)系運算符重載我們不把它放到成員函數(shù)里面。

我們直接復(fù)用庫里面的strcmp函數(shù)進(jìn)行字符串大小比較即可。此外,和日期類一樣,在寫好<和==的重載后,剩下的4個關(guān)系運算符我們直接進(jìn)行復(fù)用即可。

//1.operator<
bool operator<(const string& s1, const string& s2)
{return strcmp(s1.c_str(), s2.c_str()) < 0;
}
//2.operator==
bool operator==(const string& s1, const string& s2)
{return strcmp(s1.c_str(), s2.c_str()) == 0;
}

剩下4個關(guān)系運算符我們直接復(fù)用上面兩個:

//3、operator<=
bool operator<=(const string& s1, const string& s2)
{return s1 < s2 || s1 == s2;
}
//4、operator>
bool operator>(const string& s1, const string& s2)
{return !(s1 <= s2);
}
//5、operator>=
bool operator>=(const string& s1, const string& s2)
{return !(s1 < s2);
}
//6、operator!=
bool operator!=(const string& s1, const string& s2)
{return !(s1 == s2);
}

<<流插入運算符重載

?這里我們可以通過范圍for來完成<<運算符的重載

//流插入運算符重載
ostream& operator<<(ostream& out, const string& s)
{for (auto ch : s){out << ch;}return out;
}

>>流提取運算符重載

這里實現(xiàn)的過程中我們要注意的是當(dāng)遇到空格或者換行符就要停止讀取。此外,在一開始要記得調(diào)用clear函數(shù)把原字符串的所有數(shù)據(jù)進(jìn)行清空。然后再正常往后輸入數(shù)據(jù),否則新數(shù)據(jù)累加到原數(shù)據(jù)后面,就達(dá)不到預(yù)期效果。

//流提取運算符重載
istream& operator>>(istream& in, string& s)
{//法一//先把原字符串里的數(shù)據(jù)清空才可以輸入新的數(shù)據(jù)s.clear();char ch;ch = in.get(); //使用get()函數(shù)才能獲取空格或者換行字符while (ch != ' ' && ch != '\n'){s += ch;ch = in.get();}return in;
}

這里有一個缺陷,如果我們頻繁輸入大量字符就會導(dǎo)致多次擴容,擴容會在效率上有所損耗,因此我們可以提前開辟一個128字節(jié)大小的數(shù)組,我們把每次輸入的字符放到數(shù)組里面,最后遇到停止的符號時我們就把字符+=到字符串s上。如若下標(biāo)加到127,我們就把數(shù)組的字符+=到字符串s上,然后重置數(shù)組為'\0',更新下標(biāo)為0即可。

//流提取運算符重載
istream& operator>>(istream& in, string& s)
{//法二//先把原字符串里的數(shù)據(jù)清空才可以輸入新的數(shù)據(jù)s.clear();char ch;ch = in.get(); //使用get()函數(shù)才能獲取空格或者換行字符char buff[128] = { '\0' };size_t i = 0;while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == 127){s += buff;memset(buff, '\0', 128);i = 0;}ch = in.get();}s += buff;return in;
}

getline函數(shù)

getline函數(shù)與上述寫的<<流提取運算符重載非常的相似,唯一不同的地方在于getline只有在遇到換行符才停止讀取,而<<在遇到換行符停止外,遇到空格也會停止讀取。

//getline函數(shù)
istream& getline(istream& in, string& s)
{s.clear();char ch;ch = in.get();//getline函數(shù)只有在遇到換行符才會停止while (ch != '\n'){s += ch;ch = in.get();}return in;
}

整型和字符串之間的轉(zhuǎn)換函數(shù)

  • stoi和to string

?代碼演示:

void test_string()
{int i;cin >> i;string s = to_string(i);int val = stoi(s);
}

http://www.risenshineclean.com/news/57257.html

相關(guān)文章:

  • 有沒有專門做牛仔的網(wǎng)站谷歌引擎搜索入口
  • 政府網(wǎng)站建設(shè)運維情況自查沈陽seo關(guān)鍵詞排名優(yōu)化軟件
  • 建設(shè)醫(yī)療網(wǎng)站怎樣注冊一個自己的平臺
  • 臨沂網(wǎng)站建設(shè)設(shè)計公司小紅書廣告投放平臺
  • 做早餐燒菜有什么網(wǎng)站seo綜合查詢是什么
  • 內(nèi)網(wǎng)網(wǎng)站建設(shè)方案廣告視頻
  • 杭州做網(wǎng)站需要多少錢站長統(tǒng)計網(wǎng)站統(tǒng)計
  • 艾辰做網(wǎng)站黑帽seo技巧
  • 有沒有專業(yè)收費做網(wǎng)站優(yōu)化的數(shù)字化營銷
  • 塘下網(wǎng)站建設(shè)深圳網(wǎng)絡(luò)推廣公司排名
  • 凡科網(wǎng)做的網(wǎng)站保存后就上傳了嗎深圳網(wǎng)絡(luò)推廣渠道
  • 網(wǎng)站制作哪家實惠seo權(quán)重優(yōu)化軟件
  • 深圳網(wǎng)站維護優(yōu)化百度識別圖片找圖
  • 單位加強網(wǎng)站建設(shè)網(wǎng)絡(luò)推廣自學(xué)
  • 徐州做網(wǎng)站需要多少錢seo自媒體培訓(xùn)
  • 如何寫代碼做網(wǎng)站百度關(guān)鍵詞排名軟件
  • 滕州做網(wǎng)站網(wǎng)店代運營騙局流程
  • 做網(wǎng)站的公司都是小公司百度關(guān)鍵詞模擬點擊軟件
  • 好的網(wǎng)站具備什么條件找代寫文章寫手
  • 衡陽網(wǎng)站建設(shè)制作全媒體運營師報名入口
  • 房產(chǎn)資訊什么網(wǎng)站做的好廈門百度推廣開戶
  • 房產(chǎn)網(wǎng)站開發(fā)文檔合肥seo軟件
  • 網(wǎng)站建設(shè)屬于seo數(shù)據(jù)
  • java網(wǎng)站開發(fā)實例視頻教程朋友圈廣告代理商官網(wǎng)
  • 網(wǎng)站設(shè)置關(guān)于我們怎么做推廣策略怎么寫
  • WordPress首頁站內(nèi)搜索開魯seo網(wǎng)站
  • 常熟網(wǎng)站開發(fā)搜索大全引擎入口
  • 利用淘寶視頻服務(wù)做視頻網(wǎng)站百度快照如何優(yōu)化
  • 網(wǎng)站新建設(shè)請示cpa游戲推廣聯(lián)盟
  • 新增備案網(wǎng)站常見的網(wǎng)絡(luò)推廣方式包括