C 从文件中读取矩阵,并带有多个定界符
C++ Read matrices from file with multiple delimiters
因此,我给了一个带有十个矩阵的文件,我想从文件中读取这些矩阵,然后将它们保存到向量/阵列中,每个矩阵都存储在vector中或一个向量或一个大批。但是,这些矩阵的格式使我很难阅读数据(我从输入文件中阅读不好)。
该文件具有以下格式。每个矩阵的元素被"分开。每一行被";"分开,每个矩阵都由" |"分开。例如,三个2乘2个矩阵如下。
1,2; 3,4 | 0,1; 1,0 | 5,3; 3,1 |
我只想将矩阵保存到三个不同的向量中,但我不确定如何做。
我尝试了
while(getline(inFile,line)){
stringstream linestream(line);
string value;
while(getline(linestream, value, ','){
//save into vector
}
}
,但这显然很粗糙,只能通过逗号分开数据。有没有办法将数据与多个定界符分开?
谢谢!
string line;
while(getline(infile, line, '|'))
{
stringstream rowstream(line);
string row;
while(getline(rowstream, row, ';'))
{
stringstream elementstream(row);
string element;
while(getline(elementstream, element, ','))
{
cout << element << endl;
}
}
}
使用上述代码可以构建逻辑以存储单个element
。
我使用此功能将字符串拆分为字符串向量:
/**
* brief Split a string in substrings
* param sep Symbol separating the parts
* param str String to be splitted
* return Vector containing the splitted parts
* pre The separator can not be 0
* details Example :
* code
* std::string str = "abc.def.ghi..jkl.";
* std::vector<std::string> split_str = split('.', str); // the vector is ["abc", "def", "ghi", "", "jkl", ""]
* endcode
*/
std::vector<std::string> split(char sep, const std::string& str);
std::vector<std::string> split(char sep, const std::string& str)
{
assert(sep != 0 && "PRE: the separator is null");
std::vector<std::string> s;
unsigned long int i = 0;
for(unsigned long int j = 0; j < str.length(); ++j)
{
if(str[j] == sep)
{
s.push_back(str.substr(i, j - i));
i = j + 1;
}
}
s.push_back(str.substr(i, str.size() - i));
return s;
}
然后,期望您有一个类矩阵,您可以做类似的事情:
std::string matrices_str;
std::ifstream matrix_file(matrix_file_name.c_str());
matrix_file >> matrices_str;
const std::vector<std::string> matrices = split('|', matrices_str);
std::vector<Matrix<double> > M(matrices.size());
for(unsigned long int i = 0; i < matrices.size(); ++i)
{
const std::string& matrix = matrices[i];
const std::vector<std::string> rows = split(';', matrix);
for(unsigned long int j = 0; j < rows.size(); ++j)
{
const std::string& row = matrix[i];
const std::vector<std::string> elements = split(',', row);
for(unsigned long int k = 0; k < elements.size(); ++k)
{
const std::string& element = elements[k];
if(j == 0 && k == 0)
M[i].resize(rows.size(), elements.size());
std::istringstream iss(element);
iss >> M[i](j,k);
}
}
}
或压缩代码:
std::string matrices_str;
std::ifstream matrix_file(matrix_file_name.c_str());
matrix_file >> matrices_str;
const std::vector<std::string> matrices = split('|', matrices_str);
std::vector<Matrix<double> > M(matrices.size());
for(unsigned long int i = 0; i < matrices.size(); ++i)
{
const std::vector<std::string> rows = split(';', matrices[i]);
for(unsigned long int j = 0; j < rows.size(); ++j)
{
const std::vector<std::string> elements = split(',', matrix[i]);
for(unsigned long int k = 0; k < elements.size(); ++k)
{
if(j == 0 && k == 0)
M[i].resize(rows.size(), elements[k].size());
std::istringstream iss(elements[k]);
iss >> M[i](j,k);
}
}
}
您可以使用finite state machine
概念。您需要为每个步骤定义状态。阅读一个字符,然后决定它是什么(数字或定界符)。
这是您如何做到的概念。有关更多阅读,请在Internet上查看此内容。text parsing
,finite state machine
,lexical analyzer
,formal grammar
enum State
{
DECIMAL_NUMBER,
COMMA_D,
SEMICOLON_D,
PIPE_D,
ERROR_STATE,
};
char GetChar()
{
// implement proper reading from file
static char* input = "1,2;3,4|0,1;1,0|5,3;3,1|";
static int index = 0;
return input[index++];
}
State GetState(char c)
{
if ( isdigit(c) )
{
return DECIMAL_NUMBER;
}
else if ( c == ',' )
{
return COMMA_D;
}
else if ( c == ';' )
{
return SEMICOLON_D;
}
else if ( c == '|' )
{
return PIPE_D;
}
return ERROR_STATE;
}
int main(char* argv[], int argc)
{
char c;
while ( c = GetChar() )
{
State s = GetState(c);
switch ( c )
{
case DECIMAL_NUMBER:
// read numbers
break;
case COMMA_D:
// append into row
break;
case SEMICOLON_D:
// next row
break;
case PIPE_D:
// finish one matrix
break;
case ERROR_STATE:
// syntax error
break;
default:
break;
}
}
return 0;
}
您实际上已映射到非常简单的字节机。
从零矩阵开始,可以跟踪您正在编写的矩阵中的位置。一次阅读一个角色。如果字符是数字,则将矩阵中的当前数乘以10,然后将数字添加到其上,如果字符是逗号,请在该行中的下一个数字,如果字符是半彩色的下一行,如果字符是管道,请启动一个新矩阵。
如果数字是浮点,您可能不想这样做。我将它们保存在缓冲区中,并使用分析浮点数的标准方法。但是,除此之外,您实际上不需要保持太多复杂状态或建造大型解析器。您可能需要在以后的阶段添加错误处理,但是即使在那里,错误处理也很琐碎,并且仅取决于您扫描的当前字符。
- .cpp和.h文件中的模板专用化声明
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 文本文件中的单词链表
- CMake-按正确顺序将项目与C运行时对象文件链接
- 使用新行和不使用新行读取文件
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 挂起和取消挂起一个文件DLL
- 如何确定我已使用非编码文件到达 EOF?
- 命名空间中具有.h和.cpp文件的类
- 如何使用ndk-build.cmd构建Android.so文件
- 从包含m行的文件中提取n行,必要时(惰性地)重复该文件
- 读取文件并输入到矢量中
- 在C++中查找文件
- c++库的公共头文件中应该包含什么
- 用c++从输入文件中读取另一行
- Cppcheck生成xml转储文件
- 读取文件的最后一行并输入到链接列表时出错
- 从文本文件中读取并通过定界符分开
- 从文件中分配变量,并使用定界符分配
- C 从文件中读取矩阵,并带有多个定界符