STL?string!!!

一、引言

? ? ? ? 在之前的文章中,我們一同學習了有關類和對象、模板、動態內存管理的相關知識,那么接下來一段時間我們將要趁熱打鐵,一起來手撕C++庫中最重要的一個庫----STL中的一些容器,在手撕它們之前,我將先介紹一下對應的容器,在這個過程中,我們將加深之前學習過的相關知識。

二、string的前置內容

? ? ? ? 1、string的介紹

? ? ? ? 事實上string并不是STL中的一個容器,這是由于C++的發展歷史的原因,但是隨著語言的發展,string與STL中的容器的風格以及使用方法已經有著很高的耦合度了,所以我將它放在STL這里一起學習。

? ? ? ? string是一個字符串類,可以借助其提供的接口進行字符串的各種增刪查改操作,它的底層其實就是一個存儲字符數組的順序表。

·? ? ? ? 2、string中的常用接口

? ? ? ? 事實上,string所提供的接口是有很多冗余的,大概有100多個接口,在實現部分都只涉及到一些常用的接口,通過這些常用的接口已經可以處理平常所能遇到的幾乎所有情況了,如果需要了解所有接口或者對于以下接口的使用還不太熟悉的話,可以調轉到以下網站了解:cplusplus.com - The C++ Resources Networkhttps://legacy.cplusplus.com/三、手撕一個string類

? ? ? ? 1、string類的成員變量及整體的框架

? ? ? ? 為了與庫中的string區分,我們將在自己的命名空間中進行定義相關變量,這個命名空間的名字是無所謂的,為了方便起見,我將直接展開std命名空間,但是在真實場景下,不直接展開會更好一些?

? ? ? ? 同時在這里說明一下,我們將在寫一個函數之前先將庫中的函數頭放在前面,以其為導引,同時在這里簡單的說明一下該函數的作用

? ? ? ? string類是一個字符類型的順序表,所以需要一個內置的字符類型的指針來管理字符串中的內容,對于一個順序表,需要記錄它的長度,同時我們將動態開辟空間,所以記錄此時string中的空間是多少也是非常重要的:
????????

? ? ? ? 涉及到類似順序表的結構,_size、_capacity都是必要的,這個在以后也經常用到,同時在命名時,在成員變量之前加一個‘_’可以區分成員變量與外部變量

? ? ? ? 2、類的構造函數與析構函數

? ? ? ? 庫中的函數頭:
????????

? ? ? ? 以上是庫中所提供的所有的構造函數,我們只實現圖中圈出的兩個,還有幾個是拷貝構造函數,在后面會實現,同時由于析構函數名一定并且沒有返回值,不傳參,這里就不展示了

? ? ? ? 一般來說構造函數我們更傾向于在初始化列表進行初始化,但是由于要開空間,同時對于一個內置類型來說,在函數體內賦值和在初始化列表進行初始化的效率差別不是很大,所以我都采用函數體內賦值:
????????

? ? ? ?可以看到,在上面我們只實現了一個構造函數但是由于它是帶缺省值的,如果不傳參默認會構造一個空串,所以與庫中的函數是配合的,需要注意的是,在開空間時一定要多開一個空間,這個位置是留給‘\0’的

? ? ? ? 3、類中留給類外讀取信息的幾個簡單函數

? ? ? ? 庫中的函數頭:

? ? ? ? ????????(1).size函數:返回此時字符串中的元素個數
????????????????

? ? ? ????????? (2).c_str函數:返回一個c風格的字符串

????????????????

? ? ? ? ? ? ? ? 這兩個函數實現起來是很簡單的,就不做過多的介紹了:
????????????????

? ? ? ? 4、[]操作符重載

? ? ? ? 庫中的函數頭:
????????

? ? ? ? []操作符重載的作用是讓我們實現的類類型可以像正常的數組一樣使用[]訪問下標的方式來訪問字符串中指定位置的內容,使用起來很方便,同時代碼的可讀性變高

? ? ? ? 可以看到,該操作重載有兩個函數重載,這兩個函數重載都是很有必要的,當this指針不被const修飾時,函數提供給非const類型使用,可讀可寫;當this指針被const修飾時,函數提供給const類型使用,只讀不寫:
????????

? ? ? ? 可以看到,該函數的實現也是非常的方便的,并且兩個重載的內容也一模一樣,這時候我們可以使用模板來簡化代碼,但由于這是很簡單的兩個重載,所以沒有必要,在以后STL中其它部分,我們會大量的使用模板的相關知識

? ? ? ? 5、完成迭代器的封裝

? ? ? ? 庫中的函數頭:
? ? ? ? ? ? ? ? (1).begin

????????????????

? ? ? ? ? ? ? ? (2).end

????????????????

? ? ? ? 迭代器是STL的相關容器中的一個重要工具,常被用來遍歷容器,它是類中定義的一個類型,使用起來和指針非常相似,在類中定義類型有兩種方式,封裝內部類和typedef,很明顯使用指針就可以直接遍歷一個字符類型的數組,所以string類的迭代器我們可以直接使用typedef封裝字符指針的方式

? ? ? ? 了解迭代器之后,我們還需要了解begin和end是留給用戶使用迭代器的兩個接口,begin返回指向首元素的迭代器,end返回指向末尾元素下一個位置的迭代器,它們也都進行了重載,同樣分為只讀不寫和可讀可寫,在之前已經詳細介紹過,這里就不多介紹了:
????????

? ? ? ? 6、一個特殊的常量

? ? ? ? 庫中的介紹:
????????

? ? ? ? 在庫中定義了一個靜態成員變量npos,它的值是-1,但由于它是size_t類型的,所以實質上是一個非常大的正整數,我們默認一個自負床不會有這么長,所以在庫中的函數將npos這一靜態成員變量當作無窮大來使用:
????????

? ? ? ? 在這里需要注意:類中的靜態成員變量一定要記得在類外進行定義,雖然const修飾的靜態成員變量是可以i直接在類內聲明時直接定義的,但為了統一性,這里我還是在類外進行了定義

? ? ? ?7、拷貝構造函數

? ? ? ? 庫中的函數頭:
????????

? ? ? ? 拷貝構造函數的作用在這里就不多介紹了,它在之后的函數返回一個string類型、傳參時傳一個string類型、賦值運算符重載時都會用到:
????????

? ? ? ? 8、開空間函數

? ? ? ? 庫中的函數頭:
? ? ? ? reserve:開指定大小的空間,將原數據進行拷貝,剩余部分不做處理

? ? ? ??

????????

? ? ? ? 9、插入相關函數-----append

? ? ? ? 庫中的函數頭:
????????

? ? ? ? append函數是用于在字符串末尾插入的函數,可以看到庫中提供了很多的函數重載,接下來我們只會實現以上圈出的幾個,同時我們將借助缺省值簡化代碼:
????????? ? ? ?

? ? ? ? 糾正一下:不小心忘記進行:_size += n\_size += sublen啦,這是在寫完之后測試的時候發現的,所以一定要邊寫邊測試啊!!!

? ? ? ? 10、交換函數

? ? ? ? 庫中的函數頭:
????????

? ? ? ? swap函數顧名思義就是交換兩個string類對象,需要注意的是我們將完成深拷貝,也就是說要重新開空間,而不能簡單的交換兩個類對象的成員變量,這時候我們可以借助算法庫中提供的swap函數,它可以幫助我們完成深拷貝,事實上我們可以直接進行深拷貝,但是借助算法庫實現會更簡單:

????????

? ? ? ? 需要注意的是:在這里我們需要指定標準命名空間

? ? ? ? 11、賦值運算符重載

? ? ? ? 庫中的函數頭:
????????

? ? ? ? 庫中海還有該函數的其它重載,但其實都可以通過該函數完成剩余操作,所以只實現這一個,同時,由于我們可以借助一種更簡單的方式來完成該函數的實現,所以接下來我對該函數的實現時,函數頭與庫中的略有差異,但是對于用戶的使用是相同的:
????????

? ? ? ? 對以上代碼做一下解釋:我們的函數實參傳給形參會進行臨時拷貝,這是會調用我們之前實現過的拷貝構造函數進行深拷貝,再交換*this與str,*this就變成了str,str是形參,出作用域銷毀,調用析構函數,不會造成內存泄漏,*this出函數還存在,進行傳引用返回

? ? ? ? 12、其它運算符重載

? ? ? ? 由于接下來都是正常的運算符重載,功能也是顯而易見的,所以在這里就不提供庫中的函數頭了,直接進行相關的實現:
????????

//其它運算符重載//+=運算符重載
string& operator+=(const string& str)
{return append(str);
}
string& operator+=(const char* s)
{return append(s);
}
string& operator+=(char c)
{return append(1, c);
}
//+運算符重載
string operator+(const string& str)
{string strtmp(*this);return (strtmp += str);
}
string operator+(const char* s)
{string strtmp(*this);return (strtmp += s);
}
string operator+(char c)
{string strtmp(*this);return (strtmp += c);
}
//<運算符重載
bool operator < (const string& s) const
{int minlen = _size;if (s._size < _size){minlen = s._size;}for (int i = 0; i < minlen; i++){if (_str[i] != s._str[i]){return _str[i] < s._str[i];}}return _size < s._size;
}
//==運算符重載
bool operator==(const string& s) const
{if (_size != s._size) return false;for (int i = 0; i < _size; i++){if (_str[i] != s._str[i]){return false;}}return true;
}
//<=運算符重載
bool operator<=(const string& s) const
{return ((*this < s) || (*this == s));
}
//>運算符重載
bool operator>(const string& s) const
{return (!(*this < s) && !(*this == s));
}
//>=運算符重載
bool operator>=(const string& s) const
{return ((*this > s) || (*this == s));
}
//!=運算符重載
bool operator!=(const string& s) const
{return !(*this == s);
}

? ? ? ? 以上就是所有可能用到的運算符重載了,由于很長,所以我將代碼直接放在上面,可以看到,由于這些邏輯運算符有天然的互斥性,所以我們可以很好的進行代碼復用,大大提高了代碼的質量

? ? ? ? 13、插入相關函數-----push_back

? ? ? ? 庫中的函數頭:
????????

? ? ? ? 該函數的作用是在字符串末尾插入一個字符,無返回值:
????????

? ? ? ? 在這個位置我們可以直接進行代碼復用

? ? ? ? 14、插入相關函數-----insert

? ? ? ? 庫中的函數頭:
????????

? ? ? ? 庫中對于插入函數也是提供了非常多的重載,我們只實現圖中圈出的幾個,同時我們會使用缺省值的方式簡化代碼:
?????????

//插入函數
string& insert(size_t pos, const string& str, size_t subpos = 0, size_t sublen = npos)
{assert(pos < _size);assert(subpos < str._size);if (subpos + sublen >= str._size) sublen = str._size - subpos;if (_capacity < _size + sublen + 1){reserve(_size + sublen + 1 + 0.5 * sublen);}int end = _size , next = end + sublen;while (next > pos){_str[next--] = _str[end--];}for (int i = 0; i < sublen; i++){_str[pos + i] = str._str[i];}_size += sublen;return *this;
}
string& insert(size_t pos, const char* s, size_t n = npos)
{string strtmp(s);return insert(pos, s, 0, n);
}
string& insert(size_t pos, size_t n, char c)
{assert(pos < _size);if (_capacity < _size + n + 1){reserve(_size + n + 1 + 0.5 * n);}int end = _size, next = end + n;while (next > pos){_str[next] = _str[end];}for (int i = 0; i < n; i++){_str[pos + n] = c;}_size += n;return *this;
}

? ? ? ? 可以看到,在上面我們也進行了一定程度的代碼復用,所以代碼復用是非常重要的,可以大大提高代碼質量

? ? ? ? 15、刪除函數

? ? ? ? 庫中的函數頭:
????????

? ? ? ? erase函數的作用是從pos位置開始,刪除len長度的字符:
????????

? ? ? ? 16、查找相關函數

? ? ? ? 庫中的函數頭:
????????

? ? ? ? 庫中對于查找函數也是實現了多個函數重載,在這里我們只實現上面圈出的兩個,其他的通過借助這兩個函數也是都可以完成的:

????????

? ? ? ? 在上面的實現中我們借助了C語言常用的幾個函數,簡化了代碼

? ? ? ? 17、返回子串的函數

? ? ? ? 庫中的函數頭:
????????

? ? ? ? 該函數的作用是返回從pos位置開始len長度的子串:

????????

? ? ? ? 18、清理函數

? ? ? ? 庫中的函數頭:

????????

? ? ? ? 該函數可以清空字符串中的數據:
????????

四、最終的string類

? ? ? ? 終于,我們一起寫完了一個簡陋版的string類,需要注意的是在這個過程中我們更關注的是了解string的使用、加深對于類和對象等知識的理解和提升我們的代碼能力,并不是寫出一個更好的string類,最終完成的string類如下:
????????

namespace bea
{class string{public://相關函數//構造函數string(const char* s = ""){int n = strlen(s);_str = new char[n + 1];memcpy(_str, s, n + 1);_size = n;_capacity = n;}//size函數size_t size() const{return _size;}//c_str函數const char* c_str() const{return _str;}//[]操作符重載// // 普通類型char& operator[](size_t pos){assert(pos < _size);return _str[pos];}//const類型const char& operator[](size_t pos) const{assert(pos < _size);return _str[pos];}//迭代器相關接口//先進行類型的封裝typedef char* iterator;typedef const char* const_iterator;//begin函數iterator begin(){return _str;}const_iterator begin() const{return _str;}//end函數iterator end(){return _str + _size;}const_iterator end() const{return _str + _size;}string(const string& str){_str = new char[str._capacity + 1];memcpy(_str, str._str, _size + 1);_size = str._size;_capacity = str._capacity;}//開空間函數void reserve(size_t n = 0){if (n > _capacity){char* strtmp = new char[n + 1];memcpy(strtmp, _str, _size + 1);delete[] _str;_str = strtmp;_capacity = n;}}//尾接函數//尾接C風格字符串//接入s字符串的前n個字符string& append(const char* s, size_t n = npos){size_t len = strlen(s);if (n > len) n = len;if (_capacity < _size + n + 1){reserve(_size + n + 1 + 0.5 * n);}for (int i = 0; i < n; i++){_str[_size + i] = s[i];}_str[_size + n + 1] = '\0';_size += n;return *this;}//尾接一個string//接入str的subpos開始sublen長度的子串string& append(const string& str, size_t subpos = 0, size_t sublen = npos){assert(subpos < str._size);if (subpos + sublen >= str._size) sublen = _size - subpos;if (_capacity < _size + sublen + 1){reserve(_size + sublen + 1 + 0.5 * sublen);}for (int i = 0; i < sublen; i++){_str[_size + i] = str._str[i];}_str[_size + sublen + 1] = '\0';_size += sublen;return *this;}//尾接n個chstring& append(size_t n, char ch){if (_capacity < _size + n + 1){reserve(_size + n + n * 0.5);}for (int i = 0; i < n; i++){_str[_size + i] = ch;}_str[_size + n + 1] = '\0';_size += n;return *this;}//交換函數void swap(string& str){std::swap(_str, str._str);std::swap(_size, str._size);std::swap(_capacity, str._capacity);}//賦值運算符重載string& operator=(string str){swap(str);return *this;}//其它運算符重載//+=運算符重載string& operator+=(const string& str){return append(str);}string& operator+=(const char* s){return append(s);}string& operator+=(char c){return append(1, c);}//+運算符重載string operator+(const string& str){string strtmp(*this);return (strtmp += str);}string operator+(const char* s){string strtmp(*this);return (strtmp += s);}string operator+(char c){string strtmp(*this);return (strtmp += c);}//<運算符重載bool operator < (const string& s) const{int minlen = _size;if (s._size < _size){minlen = s._size;}for (int i = 0; i < minlen; i++){if (_str[i] != s._str[i]){return _str[i] < s._str[i];}}return _size < s._size;}//==運算符重載bool operator==(const string& s) const{if (_size != s._size) return false;for (int i = 0; i < _size; i++){if (_str[i] != s._str[i]){return false;}}return true;}//<=運算符重載bool operator<=(const string& s) const{return ((*this < s) || (*this == s));}//>運算符重載bool operator>(const string& s) const{return (!(*this < s) && !(*this == s));}//>=運算符重載bool operator>=(const string& s) const{return ((*this > s) || (*this == s));}//!=運算符重載bool operator!=(const string& s) const{return !(*this == s);}//push_back函數void push_back(char c){*this += c;}//插入函數string& insert(size_t pos, const string& str, size_t subpos = 0, size_t sublen = npos){assert(pos < _size);assert(subpos < str._size);if (subpos + sublen >= str._size) sublen = str._size - subpos;if (_capacity < _size + sublen + 1){reserve(_size + sublen + 1 + 0.5 * sublen);}int end = _size , next = end + sublen;while (next > pos){_str[next--] = _str[end--];}for (int i = 0; i < sublen; i++){_str[pos + i] = str._str[i];}_str[pos + sublen + 1] = '\0';_size += sublen;return *this;}string& insert(size_t pos, const char* s, size_t n = npos){string strtmp(s);return insert(pos, s, 0, n);}string& insert(size_t pos, size_t n, char c){assert(pos < _size);if (_capacity < _size + n + 1){reserve(_size + n + 1 + 0.5 * n);}int end = _size, next = end + n;while (next > pos){_str[next] = _str[end];}for (int i = 0; i < n; i++){_str[pos + n] = c;}_str[pos + n + 1] = '\0';_size += n;return *this;}//刪除函數string& erase(size_t pos = 0, size_t len = npos){assert(pos < _size);if (pos + len >= _size){_str[pos] = '\0';_size -= len;return *this;}int end = pos + len, front = pos;while (front < _size){_str[front++] = _str[end++];}_size -= len;_str[pos + len + 1] = '\0';return *this;}//找字符函數size_t find(char ch, size_t pos = 0){assert(pos < _size);for (int i = pos; i < _size; i++){if (_str[i] == ch) return i;}return npos;}//找字符串size_t find(const char* str, size_t pos = 0){assert(pos < _size);const char* ptr = strstr(_str + pos, str);if (ptr){return ptr - _str;}else{return npos;}}//子串函數string substr(size_t pos = 0, size_t len = npos){if (pos == 0 && len >= _size) return *this;if (pos + len >= _size) len = _size - pos;string tmp;for (int i = pos; i < pos + len; i++) tmp.push_back(_str[i]);return tmp;}//清除函數void clear(){_str[0] = '\0';_size = 0;}//析構函數~string(){delete[] _str;_str = nullptr;_size = _capacity = 0;}private:char* _str;size_t _size;size_t _capacity;static const size_t npos;};const size_t string::npos = -1;
}

五、結語

? ? ? ? 以上就是本期關于手撕string類的所有內容了,感謝大家的閱讀,歡迎各位于晏、亦菲和我一起交流、學習、進步!!!? ? ? ??

????????

????????
????????
????????

? ? ??

????????????????

? ? ? ? ? ? ?
????????????????? ? ? ??

????????
????????

????????????????????????????????

????????????????

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/79612.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79612.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/79612.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

低版本GUI配置SAProuter

1、注意配置SAProuter時&#xff0c;必須添加后面的/H/ 如&#xff1a;/H/sap.sapzx.cn/H/ 2、或者有時需要配置service文件&#xff08;C:\WINDOWS \system32\drivers\etc\service&#xff09; sapmsEP1 3600/tcp

springBoot中自定義一個validation注解,實現指定枚舉值校驗

緣由 在后臺寫接口的時候&#xff0c;經常會出現dto某個屬性是映射到一個枚舉的情況。有時候還會出現只能映射到枚舉類中部分枚舉值的情況。以前都是在service里面自行判斷&#xff0c;很多地方代碼冗余&#xff0c;所以就想著弄一個自定義的validation注解來實現。 例如下面某…

MySQL數據庫中篇

#作者&#xff1a;允砸兒 #日期&#xff1a;乙巳青蛇年 四月初九 筆者繼續帶朋友們了解mysql數據庫中篇的內容。多了不說&#xff0c;少了不嘮&#xff0c;咱們直接就開寫。 書接上回筆者在上篇中介紹了什么是數據庫和數據庫的一些基礎的概念&#xff0c;以及mysql數據庫的…

AI如何重塑DDoS防護行業?六大變革與未來展望

隨著AI技術的深度滲透&#xff0c;DDoS防護行業正經歷一場從“規則驅動”到“智能驅動”的范式革命。傳統依賴靜態閾值和人工規則的防御模式已難以應對新型攻擊&#xff0c;而AI的引入不僅提升了檢測精度&#xff0c;更重構了防護體系的底層邏輯。以下是AI帶來的六大核心變革及…

五一作業-day04

文章目錄 1. **ps -ef是顯示當前系統進程的命令,統計下當前系統一共有多少進程**2. **last命令用于顯示所用用戶最近1次登錄情況,awk可以取出某一列,現在要取出last命令第1列并去重統計次數**3. **secure日志是用戶的登錄日志,過濾出secure日志中的Failed password的次數(用課堂…

抽獎系統(基于Tkinter)

一、抽獎規則及使用方法 抽獎規則&#xff1a; 從1-138個號碼中隨機抽獎&#xff0c;共進行n輪抽獎&#xff0c;每個號碼僅有一次中獎機會&#xff0c;即已中獎的號碼不會再次中獎。 使用方法&#xff1a; 要求開始抽獎后屏幕上隨機滾動顯示中獎號碼&#xff0c;點擊“STOP”之…

window 系統 使用ollama + docker + deepseek R1+ Dify 搭建本地個人助手

1. 下載ollama &#xff0c;官網 下載地址&#xff1a;Download Ollama on macOS&#xff0c;選擇 Window 下載完成后&#xff0c;可在終端 使用 ollama --version 2. 下載 本地大模型&#xff0c;這里下載deepseek r1 7b 3.下載Embed模型 Embed模型 是文本工具向量化的核心工…

【學習筆記】 強化學習:實用方法論

作者選擇了由 Ian Goodfellow、Yoshua Bengio 和 Aaron Courville 三位大佬撰寫的《Deep Learning》(人工智能領域的經典教程&#xff0c;深度學習領域研究生必讀教材),開始深度學習領域學習&#xff0c;深入全面的理解深度學習的理論知識。 之前的文章參考下面的鏈接&#xf…

益鑫通汽車連接器可替代Molex,JST

# 探秘優質車規連接器 在汽車向新能源和智能化發展的進程中&#xff0c;車規連接器對汽車電子系統的穩定運行至關重要。有企業憑借技術與創新&#xff0c;在該領域表現出色。其車規連接器類型多樣&#xff0c;能滿足汽車不同系統連接需求。 一款2.54Pitch線對板連接器&#xff…

【WPF】將Bitmap圖像轉換為BitmapImage,并給Image控件顯示圖像

1.C#將Bitmap圖像轉換為BitmapImage&#xff0c;并給Image控件顯示圖像后臺實現 public void InitImage(Bitmap bitmap){try{// 將Bitmap轉換為WPF的BitmapImageBitmapImage bitmapImage;using (MemoryStream memory new MemoryStream()){bitmap.Save(memory, System.Drawing.…

Python從入門到高手8.2節-元組的常用操作符

目錄 ?8.2.1 元組的常用操作符 8.2.2 []操作符: 索引訪問元組 8.2.3 [:]操作符&#xff1a;元組的切片 8.2.4 操作符&#xff1a;元組的加法 8.2.5 *操作符&#xff1a;元組的乘法 8.2.6 元組的關系運算 8.2.7 in操作符&#xff1a;查找元素 8.2.8 五一她玩了個狗吃…

Vue3源碼學習4-effect中為什么使用WeakMap,Set?

文章目錄 前言1. 精細化依賴追蹤2. 高效的依賴收集與觸發3. 自動內存管理&#xff0c;防止內存泄漏4. 支持復雜場景 前言 在 mini vue - effect 實現中 設計&#xff08;WeakMap → Map → Set → effect函數&#xff09;有以下幾個重要原因&#xff1a; 1. 精細化依賴追蹤 W…

TinyML 邊緣智能:在資源受限 MCU 上部署 AI

前言 在物聯網(IoT)和智能邊緣計算的時代浪潮下,TinyML(微型機器學習)正以前所未有的速度改變著我們與設備交互的方式。它將 AI 推理能力放在資源極度受限的 MCU(微控制器)上,兼顧實時性、低功耗和數據隱私,成為智能家居、可穿戴設備、工業檢測等場景的核心技術。盡管…

技術白皮書:Oracle GoldenGate 優勢

本文為技術白皮書Oracle GoldenGate 優勢的翻譯及閱讀筆記。以下注釋中GoldenGate為OGG。 副標題為&#xff1a;Oracle 數據庫的變更數據捕獲 (CDC) 技術比較。版本為July, 2021, Version 2.1。 Oracle GoldenGate 被客戶和分析師公認為功能最齊全、性能最高、最值得信賴的數…

Android控件VideoView用法

一 控件UI <VideoViewandroid:id="@+id/videoView"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="fitCenter" /> 二 配置 <?xml version="1.0" encoding="u…

React 第三十六節 Router 中 useParams 的具體使用及詳細介紹

一、useParams 的基本用法 用途&#xff1a;用于在組件中獲取當前 URL 的動態路由參數&#xff08;如 /user/:id 中的 id&#xff09;。 import { Routes, Route, useParams } from react-router-dom;// 定義路由 function App() {return (<Routes><Route path"…

C++戰勝白蟻 2024年信息素養大賽復賽 C++小學/初中組 算法創意實踐挑戰賽 真題詳細解析

目錄 C++戰勝白蟻 一、題目要求 1、編程實現 2、輸入輸出 二、算法分析 三、程序編寫 四、運行結果 五、考點分析 六、 推薦資料 1、C++資料 2、Scratch資料 3、Python資料 C++戰勝白蟻 2024年信息素養大賽 C++復賽真題 一、題目要求 1、編程實現 小明因為很長…

Linux網絡編程 day4

inet_pton&#xff1a;IP 字符串 → 網絡字節序地址 ntohl&#xff1a;網絡字節序 → 主機字節序 TCP狀態轉換圖(重點) 可以通過下面這行代碼查看目前網絡狀態 netstat -apn | grep client 1、主動發起請求端 close-->SYN-->SYN_SENT-->接收ACK、SYN-->SYN_SEN…

基于springboot+vue的個人財務管理系統

開發語言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服務器&#xff1a;tomcat7數據庫&#xff1a;mysql 5.7數據庫工具&#xff1a;Navicat12開發軟件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;Maven3.3.9 系統展示 用戶信息管理 賬…

ffmpeg 元數據-avformatcontext字段 AVDictionary *metadata;

ffmpeg 元數據 1. 解釋什么是ffmpeg元數據 ffmpeg元數據是指與音視頻文件相關的附加信息&#xff0c;這些信息不直接影響音視頻內容的播放&#xff0c;但提供了關于文件內容、創作者、版權、播放參數等的有用信息。元數據在音視頻文件的處理、管理和共享中起著重要作用。 2.…