文章目錄
- 💯前言
- 💯題目描述
- 💯題目描述
- 輸入格式
- 輸出格式
- 示例輸入與輸出
- 輸入:
- 輸出:
- 💯我的做法
- 操作1:在文檔末尾插入字符串
- 操作2:截取字符串
- 操作3:在指定位置插入字符串
- 操作4:查找子串位置
- 完整代碼:
- 💯老師的做法
- 主要差異
- 代碼:
- 💯對比分析
- 相同點:
- 差異點:
- 💯擴展與優化
- 💯小結
💯前言
- 在本次編程練習中,我們的目標是設計并實現一款文字處理軟件。題目要求我們通過一系列字符串操作,模擬文字處理過程。這些操作包括字符串的拼接、截取、插入和查找,操作的結果需及時輸出。這類問題不僅考察了我們對 C++ 中字符串操作的掌握,也考察了如何根據不同需求選擇合適的數據結構和算法。通過這篇文章,我們將詳細分析題目中的要求、我的實現方法、老師的實現方式,并進行對比,最終擴展和總結整個思路。
C++ 參考手冊
💯題目描述
以下是題目原文,要求根據輸入的操作來處理文檔內容,并輸出結果:
💯題目描述
P5734 【深基6.例6】文字處理軟件
你需要開發一款文字處理軟件。最開始時輸入一個字符串作為初始文檔。可以認為文檔開頭是第 0 個字符。需要支持以下操作:
1 str
:后接插入,在文檔后面插入字符串str
,并輸出文檔的字符串;2 a b
:截取文檔部分,只保留文檔中從第a
個字符起b
個字符,并輸出文檔的字符串;3 a str
:插入片段,在文檔中第a
個字符前面插入字符串str
,并輸出文檔的字符串;4 str
:查找子串,查找字符串str
在文檔中最先的位置并輸出;如果找不到輸出-1
。
為了簡化問題,規定初始的文檔和每次操作中的 str
都不含有空格或換行。最多會有 q
次操作。
輸入格式
第一行輸入一個正整數 q
,表示操作次數。
第二行輸入一個字符串 str
,表示最開始的字符串。
第三行開始,往下 q
行,每行表示一個操作,操作如題目描述所示。
輸出格式
一共輸出 q
行。
對于每個操作 1,2,3
,根據操作的要求輸出一個字符串。
對于操作 4
,根據操作的要求輸出一個整數。
示例輸入與輸出
輸入:
4
ILove
1 Luogu
2 5 5
3 3 guGugu
4 gu
輸出:
ILoveLuogu
Luogu
LuoguGugugu
3
💯我的做法
在我自己的實現中,我依賴了 C++ 中標準庫提供的 string
類型,它使得字符串操作變得非常簡單。主要操作如下:
操作1:在文檔末尾插入字符串
我選擇了使用 +=
運算符來將字符串拼接到文檔末尾,代碼如下:
s += str;
這樣實現可以將新字符串 str
添加到當前文檔 s
的末尾,符合題目的要求。
操作2:截取字符串
對于操作2,我使用了 substr(a, b)
函數來截取文檔中的一部分。substr
函數接受兩個參數,a
為起始位置,b
為截取長度。根據題目要求,我們需要將起始位置從 1-based 轉換為 0-based,因此在調用 substr
時,將 a - 1
作為起始位置:
s = s.substr(a - 1, b);
操作3:在指定位置插入字符串
為了在指定位置插入字符串,我使用了 insert(a, str)
方法。這個方法會將字符串 str
插入到當前字符串 s
的第 a
個位置:
s.insert(a - 1, str);
注意這里的 a - 1
是因為題目給定的是 1-based 索引,而 C++ 的字符串操作是基于 0-based 索引的。
操作4:查找子串位置
對于操作4,我使用了 find(str)
函數來查找子串 str
在文檔中最早出現的位置。如果沒有找到該子串,find
函數會返回 string::npos
,表示未找到:
size_t pos = s.find(str);
if (pos == string::npos)cout << -1 << endl;
elsecout << pos << endl;
完整代碼:
#include <iostream>
#include <string>
using namespace std;int main()
{int n;cin >> n;string s;cin >> s;while(n--){int m;cin >> m;switch(m){case 1:{string s2;cin >> s2;s += s2;cout << s << endl;break;}case 2:{int a, b;cin >> a >> b;s = s.substr(a, b);cout << s << endl;break;}case 3:{int a;string s2;cin >> a >> s2;s.insert(a, s2);cout << s << endl;break;}case 4:{string s2;cin >> s2;size_t idex = s.find(s2);if(idex == string::npos)cout << -1 << endl;elsecout << idex << endl;break;}}}return 0;
}
💯老師的做法
老師的做法和我類似,核心思路沒有變化,采用了 C++ 標準庫的 string
類型及其內置的操作函數。具體代碼如下:
主要差異
-
變量初始化:
- 老師在代碼開始時就預定義了變量
a
,b
, 和str
,而我的做法是在每個操作中根據需要動態定義這些變量。 - 老師的代碼將變量定義放在了
while
循環外部,而我的做法將這些變量放在了每個switch
語句內,確保了在每個操作中只定義所需變量。
- 老師在代碼開始時就預定義了變量
-
使用
switch
語句:- 老師使用了
switch
語句來處理不同的操作,明確區分了不同的操作類型。這種方式在處理多個互斥操作時非常清晰,且便于擴展。
- 老師使用了
-
查找操作:
- 在查找子串的部分,老師也使用了
find
函數,并且處理了找不到子串時返回-1
的邏輯,和我的做法相同。
- 在查找子串的部分,老師也使用了
代碼:
#include <iostream>
#include <string>
using namespace std;int main()
{int q = 0;cin >> q;string s;cin >> s;int a, b;string str;while (q--){int m = 0;cin >> m;switch (m){case 1:cin >> str;s += str;cout << s << endl;break;case 2:cin >> a >> b;s = s.substr(a, b);cout << s << endl;break;case 3:cin >> a >> str;s.insert(a, str);cout << s << endl;break;case 4:cin >> str;size_t pos = s.find(str);if (pos == string::npos)cout << -1 << endl;elsecout << pos << endl;break;}}return 0;
}
💯對比分析
相同點:
-
操作邏輯:
- 兩種實現都處理了 4 種操作,分別是插入、截取、插入指定位置、查找子串。
- 都使用了
string
類型的操作函數,如+=
,substr
,insert
, 和find
來執行字符串操作。
-
輸入輸出:
- 輸入格式一致,讀取
q
次操作并執行,每次執行后輸出對應結果。
- 輸入格式一致,讀取
差異點:
-
變量定義:
- 我的做法在每個操作前定義變量,使得每次操作只在需要的時候初始化變量。老師則將變量統一提前定義,這在一些情況下可能更清晰,尤其是在處理較為復雜的邏輯時。
-
代碼結構:
- 我選擇了將每個操作的代碼放在
switch
語句的各個分支中,老師則將更多的內容放在switch
外部,尤其是變量的定義和初始化。
- 我選擇了將每個操作的代碼放在
💯擴展與優化
-
優化字符串拼接:
- 在頻繁拼接字符串的情況下,
+=
運算符可能會有性能問題,尤其是當字符串較長時。為了提高效率,可以使用stringstream
或vector<char>
來減少內存重分配帶來的開銷。
- 在頻繁拼接字符串的情況下,
-
邊界檢查:
- 對于操作 2 和操作 3,程序沒有進行充分的邊界檢查。如果
a
和b
超出了文檔長度范圍,應當做適當的處理。比如,在執行substr(a, b)
時,可以檢查a + b
是否超過字符串的最大長度。
- 對于操作 2 和操作 3,程序沒有進行充分的邊界檢查。如果
-
容錯性:
- 對于查找子串操作,可以加入更多的異常處理機制,例如對輸入的子串進行合法性校驗,防止空串或無效字符導致異常。
💯小結
本次文字處理軟件題目考察了 C++ 中字符串的基本操作,特別是如何通過不同的方式處理字符串的拼接、截取、插入和查找。通過兩種實現方法的對比,我們不僅看到了不同的實現方式,也發現了每種方法的優缺點。在實際編碼中,我們可以根據具體情況選擇合適的方式來實現。通過這些操作,我們能夠更深入地理解 C++ 字符串的操作特性,并提升自己的編程能力。