如何在 C++ 中解析 table 个数字
How to parse table of numbers in C++
我需要解析 table 格式为 ascii 文本的数字。每行文本有 36 个 space 分隔的带符号整数,文件中大约有 3000 行。输入文件是我在 Matlab 中生成的,因此我可以修改格式。另一方面,我也希望能够在 VHDL 中解析相同的文件,因此 ascii 文本是唯一可能的格式。
到目前为止,我有一个像这样的小程序可以遍历输入文件的所有行。我只是还没有找到一种方法来摆脱个人数字。我不是 C++ 最纯粹的人。我会考虑 fscanf() 但 36 个数字有点多了。请提出从文本文件中获取数字的实用方法。
int main()
{
string line;
ifstream myfile("CorrOut.dat");
if (!myfile.is_open())
cout << "Unable to open file";
else{
while (getline(myfile, line))
{
cout << line << '\n';
}
myfile.close();
}
return 0;
}
使用std::istringstream
。这是一个例子:
#include <sstream>
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
string line;
istringstream strm;
int num;
ifstream ifs("YourData");
while (getline(ifs, line))
{
istringstream strm(line);
while ( strm >> num )
cout << num << " ";
cout << "\n";
}
}
如果要创建 table,请使用 std::vector
或其他 suitable 容器:
#include <sstream>
#include <string>
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
string line;
// our 2 dimensional table
vector<vector<int>> table;
istringstream strm;
int num;
ifstream ifs("YourData");
while (getline(ifs, line))
{
vector<int> vInt;
istringstream strm(line);
while ( strm >> num )
vInt.push_back(num);
table.push_back(vInt);
}
}
table
向量逐行填充。请注意,我们创建了一个中间向量来存储每一行,然后该行被添加到 table.
您可以使用几种不同的方法,上面提供的方法可能是其中最快的一种,但是如果您有不同的分隔符,您可以考虑以下解决方案之一:
第一种方案,逐行读取字符串。之后,它使用 find 函数找到特定分隔符的第一个位置。然后它删除读取的数字并继续,直到不再找到定界符。
您可以通过修改定界符变量值来自定义定界符。
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string line;
ifstream myfile("CorrOut.dat");
string delimiter = " ";
size_t pos = 0;
string token;
vector<vector<int>> data;
if (!myfile.is_open())
cout << "Unable to open file";
else {
while (getline(myfile, line))
{
vector<int> temp;
pos = 0;
while ((pos = line.find(delimiter)) != std::string::npos) {
token = line.substr(0, pos);
std::cout << token << std::endl;
line.erase(0, pos + delimiter.length());
temp.push_back(atoi(token.c_str()));
}
data.push_back(temp);
}
myfile.close();
}
return 0;
}
第二种解决方案使用正则表达式,它不关心分隔符的使用,它会搜索并匹配在字符串中找到的任何整数。
#include <iostream>
#include <string>
#include <regex> // The new library introduced in C++ 11
#include <fstream>
using namespace std;
int main()
{
string line;
ifstream myfile("CorrOut.dat");
std::smatch m;
std::regex e("[-+]?\d+");
vector<vector<int>> data;
if (!myfile.is_open())
cout << "Unable to open file";
else {
while (getline(myfile, line))
{
vector<int> temp;
while (regex_search(line, m, e)) {
for (auto x : m) {
std::cout << x.str() << " ";
temp.push_back(atoi(x.str().c_str()));
}
std::cout << std::endl;
line = m.suffix().str();
}
data.push_back(temp);
}
myfile.close();
}
return 0;
}
我需要解析 table 格式为 ascii 文本的数字。每行文本有 36 个 space 分隔的带符号整数,文件中大约有 3000 行。输入文件是我在 Matlab 中生成的,因此我可以修改格式。另一方面,我也希望能够在 VHDL 中解析相同的文件,因此 ascii 文本是唯一可能的格式。
到目前为止,我有一个像这样的小程序可以遍历输入文件的所有行。我只是还没有找到一种方法来摆脱个人数字。我不是 C++ 最纯粹的人。我会考虑 fscanf() 但 36 个数字有点多了。请提出从文本文件中获取数字的实用方法。
int main()
{
string line;
ifstream myfile("CorrOut.dat");
if (!myfile.is_open())
cout << "Unable to open file";
else{
while (getline(myfile, line))
{
cout << line << '\n';
}
myfile.close();
}
return 0;
}
使用std::istringstream
。这是一个例子:
#include <sstream>
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
string line;
istringstream strm;
int num;
ifstream ifs("YourData");
while (getline(ifs, line))
{
istringstream strm(line);
while ( strm >> num )
cout << num << " ";
cout << "\n";
}
}
如果要创建 table,请使用 std::vector
或其他 suitable 容器:
#include <sstream>
#include <string>
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
string line;
// our 2 dimensional table
vector<vector<int>> table;
istringstream strm;
int num;
ifstream ifs("YourData");
while (getline(ifs, line))
{
vector<int> vInt;
istringstream strm(line);
while ( strm >> num )
vInt.push_back(num);
table.push_back(vInt);
}
}
table
向量逐行填充。请注意,我们创建了一个中间向量来存储每一行,然后该行被添加到 table.
您可以使用几种不同的方法,上面提供的方法可能是其中最快的一种,但是如果您有不同的分隔符,您可以考虑以下解决方案之一:
第一种方案,逐行读取字符串。之后,它使用 find 函数找到特定分隔符的第一个位置。然后它删除读取的数字并继续,直到不再找到定界符。 您可以通过修改定界符变量值来自定义定界符。
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string line;
ifstream myfile("CorrOut.dat");
string delimiter = " ";
size_t pos = 0;
string token;
vector<vector<int>> data;
if (!myfile.is_open())
cout << "Unable to open file";
else {
while (getline(myfile, line))
{
vector<int> temp;
pos = 0;
while ((pos = line.find(delimiter)) != std::string::npos) {
token = line.substr(0, pos);
std::cout << token << std::endl;
line.erase(0, pos + delimiter.length());
temp.push_back(atoi(token.c_str()));
}
data.push_back(temp);
}
myfile.close();
}
return 0;
}
第二种解决方案使用正则表达式,它不关心分隔符的使用,它会搜索并匹配在字符串中找到的任何整数。
#include <iostream>
#include <string>
#include <regex> // The new library introduced in C++ 11
#include <fstream>
using namespace std;
int main()
{
string line;
ifstream myfile("CorrOut.dat");
std::smatch m;
std::regex e("[-+]?\d+");
vector<vector<int>> data;
if (!myfile.is_open())
cout << "Unable to open file";
else {
while (getline(myfile, line))
{
vector<int> temp;
while (regex_search(line, m, e)) {
for (auto x : m) {
std::cout << x.str() << " ";
temp.push_back(atoi(x.str().c_str()));
}
std::cout << std::endl;
line = m.suffix().str();
}
data.push_back(temp);
}
myfile.close();
}
return 0;
}