C/C++ 依照特定格式 讀取檔案並 切割字串
tags: 部落格文章
這個新手大概很常用到,每次要用都google半天。這篇是把這些常用的函式封裝成一個物件,直接解決痛點方便操作。
因為是用 C++ 17 寫的,刷題提交用的代碼可能用不上,網站未必支援。簡單的讀檔可以參考這邊兩篇站內文。
- C 讀寫檔案 範例代碼 [行讀寫.一次讀寫全部 ]
https://charlottehong.blogspot.com/2021/04/c_7.html - C++ 讀取檔案 範例代碼 (行讀取 空格讀取 一次讀取整個文件)
https://charlottehong.blogspot.com/2021/04/c.html
讀取檔案
讀檔的問題參照上面兩篇就可以解決,這邊就概略貼上代碼就好
// 逐行讀取
vector<string> ReadFile_line(const string file_name) {
vector<string> v;
fstream fs(file_name, ios::in);
if (!fs.is_open())
throw runtime_error("Reading error.");
for (string str; getline(fs, str);)
v.emplace_back(str);
return v;
}
切割字串
傳統的C字串處理可以這樣寫
#include <string.h>
void stringSplit(char* str, const char* delim) {
char temp[64];
strcpy(temp, str);
char* pch = strtok(temp, delim);
while (pch != NULL) {
printf("%s\n", pch);
pch = strtok(NULL, delim);
}
}
C++ 11 可以這樣寫
#include <string>
void split(const string& s, vector<string>& tokens,
const string& delimiters = " ")
{
string::size_type lastPos = s.find_first_not_of(delimiters, 0);
string::size_type pos = s.find_first_of(delimiters, lastPos);
while (string::npos != pos || string::npos != lastPos) {
tokens.push_back(s.substr(lastPos, pos - lastPos));
lastPos = s.find_first_not_of(delimiters, pos);
pos = s.find_first_of(delimiters, lastPos);
}
}
C++17 可以更有效率的這樣寫
#include <string_view>
vector<string_view> splitSV(string_view strv, string_view delims = " ") {
vector<string_view> output;
for (size_t first = 0; first < strv.size();) {
const auto second = strv.find_first_of(delims, first);
if (first != second)
output.emplace_back(strv.substr(first, second - first));
if (second == string_view::npos)
break;
first = second + 1;
}
return output;
}
透過這樣的方式,就能夠把字串依照特定格式給切出來了。
封裝物件
切割完畢之後就用封裝拉,一般就是用 vector<string>
封裝,想要效率更高一點可以使用 vector<string_view>
。
因為有點長就貼到gist上了
- string_view版本:https://gist.github.com/hunandy14/425a64ab355affe215609a511db76a51
- string版本:https://gist.github.com/hunandy14/6603470a186c15192096366fa00d57e6
封裝好的物件怎麼使用有一併寫在檔案底下的test函式裡
下面就簡單說明一下,最簡單的切割
string str = "123 | 321";
OneLine line(str, " | ");
cout << line << endl;
vector<string_view>&& tokenList = line;
for (size_t i = 0; i < tokenList.size(); i++)
cout << tokenList[i] << endl;
物件本身返回的是一個 vector
這就意味了著在for裡面可以透過 line[idx] 來讀取被切割的字串
如果要從檔案讀取可以使用 openFile()
OneLine line;
line.openFile("a.txt");
while (line.getline()) {
vector<string_view>&& tokenList = line;
cout << tokenList << endl;
}
此時獲取的 tokenList 就可以用下標取出個別的字串了。
沒有留言:
張貼留言