可视化 将字符串解析为数组以进行C++

visual Parsing a string into an array for C++

本文关键字:C++ 数组 字符串 可视化      更新时间:2023-10-16

如何在C++中将字符串解析为数组?

例如:"[1:2:3:4]cd/dvd PLDS DVD-RW DU8A6SH DU53 /dev/sr0"

我想在方括号内获取一个整数数组[].所以数组包含{1, 2, 3, 4}.

下面是我写的代码,但我不确定这是否是最有效的方法。

std::string test = "[1:2:3:4]cd/dvd  PLDS  DVD-RW DU8A6SH DU53  /dev/sr0";
int begin = test.find("[");
begin = begin + 1;
std::string sub = test.substr(begin,7);
std::replace(sub.begin(), sub.end(), ':', ' ');
std::vector<int> arr;
std::stringstream ss(sub);
int temp;
while (ss >> temp)
arr.push_back(temp);

注意:有些东西不会在"["之前。"["将永远存在。每个数字将始终为一位数字。方括号内将始终有四个整数。"]"将永远存在。文本始终跟在"]"之后。

由于您正在硬编码substr()的大小,这意味着数字具有固定的位置和宽度,在这种情况下,您可以简单地使用它:

#include <string>
#include <array>
std::string test = "[1:2:3:4]cd/dvd  PLDS  DVD-RW DU8A6SH DU53  /dev/sr0";
std::array<int, 4> arr; // or: int arr[4]; pre-C++11
for(int i = 1, j = 0; i < 9; i += 2, ++j)
arr[j] = test[i]-'0';

现场演示

但是,如果不是这种情况,则不要假设关闭]的位置。 使用find()来定位它,例如:

std::string test = "[1:2:3:4]cd/dvd  PLDS  DVD-RW DU8A6SH DU53  /dev/sr0";
std::string::size_type begin = test.find('[') + 1;
std::string::size_type end = test.find(']', begin);
std::string sub = test.substr(begin, end - begin);
std::vector<int> arr;
std::istringstream iss(sub);
int temp;
while (iss >> temp) {
arr.push_back(temp);
iss.ignore();
}

现场演示

如果您使用的是 C++17 或更高版本,则可以使用std::string_viewstd::from_chars()来减少内存开销,因此您不必为substd::istringstream分配单独的std::string,甚至根本不使用std::istringstream,例如:

std::string test = "[1:2:3:4]cd/dvd  PLDS  DVD-RW DU8A6SH DU53  /dev/sr0";
std::string_view sv(test.data(), test.size());
std::string_view::size_type begin = sv.find('[') + 1;
std::string_view::size_type end = sv.find(']', begin);
std::string_view sub = sv.substr(begin, end - begin);
std::vector<int> arr;
const char *pBegin = sub.data(), *pEnd = pBegin + sub.size();
int temp;
while (pBegin < pEnd)
{
auto [ptr, ec] = std::from_chars(pBegin, pEnd, temp);
if (ec != std::errc()) break;
arr.push_back(temp);
pBegin = ptr + 1;
}

现场演示

鉴于您添加的约束,您可以尝试以下操作:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <vector>
int main() {
std::string test = "[1:2:3:4]cd/dvd  PLDS  DVD-RW DU8A6SH DU53  /dev/sr0";
std::vector<int> v(4);
{
char open_square_bracket, colon1, colon2, colon3, close_square_bracket;
std::stringstream ss(test);
ss >> open_square_bracket >> v[0] >> colon1 >> v[1] >> colon2 >> v[2] >> colon3 >> v[3] >> close_square_bracket;
}
copy(begin(v), end(v), std::ostream_iterator<int>(std::cout, ", "));
std::cout << "n";
return 0;
}

当然,重要的部分是我放在块语句中的部分,以突出显示它。这还允许您检查字符是否是它们应该的样子。否则,如果您 100% 确定格式是正确的,则可以将其简化为

std::vector<int> v(4);
char c;
std::stringstream ss(test);
ss >> c >> v[0] >> c >> v[1] >> c >> v[2] >> c >> v[3] >> c;

您也可以将其包装在 for 循环中,但如果它总是 4 个元素,何必呢?

当然,在这种情况下,可以使用std::array<>

std::array<int, 4> v;
char c;
std::stringstream ss(test);
ss >> c >> v[0] >> c >> v[1] >> c >> v[2] >> c >> v[3] >> c;

在 ideone 上运行它。

int main()
{
std::string str = "[1:2:3:4]aaa";
std::vector<int> str_chars = {};
for (unsigned int i = 0; i < str.size(); ++i)
{
char curr = str.at(i);
if (str.at(i) == '[')
{
str_chars.push_back((str.at(i + 1) - '0'));
}
else if ((str.at(i) == ':'))
{
str_chars.push_back(str.at(i + 1) - '0');
}
}
for (int i = 0; i < str_chars.size(); ++i)
{
printf("%d ", str_chars.at(i));
}
getchar();
return 0;
}