我有一个.txt文件的数字(在这种情况下都小于100)用空格分隔,用新行分隔的行。像这样:
41 53 07 91 44
52 17 13 03 21
我想将这些数字读成2d数组,与它们看起来完全一样,以便空格分隔数组的列,新行分隔行。
我可以让它以字符串形式读取行,但后来我无法分离出单个数字,并将其作为整数处理。
答案 0 :(得分:17)
试试这个:
#include <vector>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
int main()
{
// The result of the read is placed in here
// In C++, we use a vector like an array but vectors can dynamically grow
// as required when we get more data.
std::vector<std::vector<int> > data;
// Replace 'Plop' with your file name.
std::ifstream file("Plop");
std::string line;
// Read one line at a time into the variable line:
while(std::getline(file, line))
{
std::vector<int> lineData;
std::stringstream lineStream(line);
int value;
// Read an integer at a time from the line
while(lineStream >> value)
{
// Add the integers from a line to a 1D array (vector)
lineData.push_back(value);
}
// When all the integers have been read, add the 1D array
// into a 2D array (as one line in the 2D array)
data.push_back(lineData);
}
}
答案 1 :(得分:1)
好的,“完全按照它们出现”的要求意味着你需要一个参差不齐的数组,以防不同数量的列出现在不同的行中。我会用std::vector< std::vector<long> >
。每个包含的向量对应一行。
因此,每次阅读一行文本时,都要创建一个新的空矢量。
在您阅读的行上反复调用strtol
,使用push_back
将其收集到矢量中。当输出指针与输入指针相同时(这表示失败,可能是因为你到达了行的末尾),push_back
整个向量并开始下一行。
这样的事情:
std::vector< std::vector<long> > all_data;
std::string text_row;
while(getline(fin, text_row)) {
all_data.push_back();
std::vector<long>& this_row = *all_data.rend();
const char* p1 = text_row.c_str();
const char* p2;
while (1) {
long num = strtol(p2 = p1, &p1, 0);
if (p1 == p2) break;
this_row.push_back(num);
}
/* to ignore blank lines, add this code
if (this_row.empty()) all_data.pop_back();
*/
}
答案 2 :(得分:1)
以下代码显示了如何解决您的问题。它还显示了打开文件时如何使用RAII。这是获取资源时的良好做法。通过获取构造函数中的资源并在析构函数中释放它,如果抛出异常,则可以防止资源泄漏。这被认为是C ++世界的好习惯。
#include <fstream>
#include <vector>
struct FileHandle
{
std::ifstream file_;
FileHandle(std::string file_name)
{
file_.open(file_name);
}
~FileHandle()
{
file_.close();
}
};
bool next_char_is_end_of_line(std::ifstream &file)
{
bool found = false;
char c;
file.get(c);
if(c == '\n')
found = true;
file.unget();
return found;
}
int main()
{
FileHandle fh("c:\\your_file.txt");
std::vector<std::vector<int> > v;
std::vector<int> current_line;
int x;
while(fh.file_ >> x)
{
current_line.push_back(x);
if(next_char_is_end_of_line(fh.file_))
{
v.push_back(current_line);
current_line.clear();
}
}
//Then just access each std::vector<std::vector<int>>
//v[0].size(); ...
return 0;
}
此代码通过将每行上的所有数字放入单独的向量中来为您提供“锯齿状”向量。然后将该载体添加到主载体中。因此“向量”中的每一行可以具有不同的长度。我想你明白了......
祝你好运!答案 3 :(得分:0)
尝试stringstream。
答案 4 :(得分:0)
实际上有两个问题,在这里:
你谈到“二维数组”:这是一个要求还是一个假设?是2x5尺寸要求还是只是样品?
您谈到了文件布局。这是强制性的,还是不是?您是否应该承认(和检查)最终会误导更多数字或错位?如果第一行有6个数字,第二行有4个数字,你需要做什么?
一个非常简单的解决方案是使用2x5阵列并用保护循环填充它:
#include <iostream>
#include <fstream>
#include <iomanip>
#include <stdexcept>
const int ROWS=2;
const int COLS=5;
int main(int argc, char** argv)
{
int m[ROWS][COLS];
try
{
std::ifstream s(argv[1]);
if(!s) throw std::runtime_error("cannot open file");
for(int r=0; r<ROWS; ++r)
for(int c=0; c<COLS; ++c)
if(!(s >>m[r][c])
throw std::runtime_error("insufficient or bad input");
}
catch(const std::exception& e)
{
std::cout << "Reading error: " << e.what() << std::endl;
return -1;
}
std::cout << "read matrix is \n";
for(int r=0; r<ROWS; ++r)
{
for(int c=0; c<COLS; ++c)
std::cout << std::setw(8) << m[r][c];
std::cout << '\n';
}
std::cout << std::endl;
return 0;
}
这将读取由“空白”分隔的10个数字,无论分布和对齐如何。 (这是2x5是一个结论。)
另一方面,您可能需要检测自己矩阵的宽度:文件可以包含任意数量的行,每个行的长度都是多少。
在这种情况下,您需要一个“灵活的结构”,您需要识别线条中的线条和元素。
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <iomanip>
#include <stdexcept>
#include <utility>
int main(int argc, char** argv)
{
std::vector<std::vector<int> > m;
try
{
std::ifstream fs(argv[1]);
if(!fs) throw std::runtime_error("cannot open input file");
while(fs)
{
std::string line;
std::getline(fs,line);
std::vector<int> row;
std::stringstream ss(line);
int x;
while(ss >> x)
row.push_back(x);
if(!row.empty())
m.emplace_back(std::move(row));
}
}
catch(const std::exception& e)
{
std::cout << "Reading error: " << e.what() << std::endl;
return -1;
}
std::cout << "read lines: \n";
for(auto i=m.begin(); i!=m.end(); ++i)
{
for(auto j=i->begin(); j!=i->end(); ++j)
std::cout << std::setw(8) << *j;
std::cout << '\n';
}
std::cout << std::endl;
return 0;
}