使用get_line读取文件时,提取带括号的字符串中的数字 一个问题让我困惑了C++初学者一段时间。
我将大量数字数据以以下方式存储在文件中:使用get_line读取文件时,提取带括号的字符串中的数字 一个问题让我困惑了C++初学者一段时间。,c++,C++,我将大量数字数据以以下方式存储在文件中: (123 34412 24) (13 34324 2214) (143 21342 24123) (1323 341422 23244) (14123 32342 2413) .... 我想阅读这些数据,希望提取第一列来做一些科学计算,第二列和第三列也希望同时提取 我不知道它是什么数据结构,并且检查了一些参考文献,发现没有答案,似乎不是列表、向量等 我希望使用如下代码来完成这项工作 #include <fstream> #include &
(123 34412 24)
(13 34324 2214)
(143 21342 24123)
(1323 341422 23244)
(14123 32342 2413)
....
我想阅读这些数据,希望提取第一列来做一些科学计算,第二列和第三列也希望同时提取
我不知道它是什么数据结构,并且检查了一些参考文献,发现没有答案,似乎不是列表、向量等
我希望使用如下代码来完成这项工作
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char* argv[])
{
ifstream file("input.dat");
string lineBuf;
int *col1[], *col2[], *col3[];
if (file.is_open())
{
while(getline(file, lineBuf)
{
// how to convert lineBuf to separated numbers
// and assign to col1 col2 col3 separately here?
}
}
return 0;
}
虽然我无法获得正确的bc输出,但您不需要在这里使用getline或任何字符串操作。我们可以利用这样一个事实:操作符>>只读取调用它的类型,而忽略读取每个数字的空白
char eater; // this is to consume the ( and ) on each line
int number1, number2, number3;
std::ifstream fin("some_file_name.txt");
while (fin >> eater >> number1 >> number2 >> number3 >> eater) // will stop when it can't read anymore
{
// do something with the numbers
} // loop back and read the next line
在上面的代码中,第一个>>食客将读取单个字符。这将吃掉开始时的数字,允许我们使用运算符>>获取3个数字。最后一个>>进食者在最后消耗了,让我们准备好阅读下一行。尝试使用此片段,并根据需要对其进行修改:
std::list<float> readNumberListFromLine(const std::string &line) {
std::stringstream stream(line);
std::list<float> nums;
char chr = 0;
// Wait for a "(" token.
while(1 == 1) {
stream >> chr;
// If failed to read a character, it means eof
if (stream.fail()) break;
if (chr == '(') break;
}
// Clear the stream state, to clear the "fail" bit, to allow reading more while we
// check on this state
stream.clear();
while(1 == 1) {
float num;
stream >> num;
// If failed to read a number, stream of numbers have stopped, don't read numbers more.
if (stream.fail()) { break; }
nums.push_front(num);
}
stream.clear();
// This part shouldn't be like that, DRY principle says "Don't repeat yourself"
// This should be in a function because it is a repeat of the first loop
// But this would have templates and things that aren't simple
while(1 == 1) {
stream >> chr;
if (stream.fail()) return std::list<float>();
if (chr == ')') break;
}
return nums;
}
void printList(const std::list<float> &list) {
// We don't want pop to affect the original
std::list<float> copy = list;
while (!copy.empty()) {
// We pushed on the front, so when we pop, pop from back, push/pop is a LIFO mechanism
// Last-in-first-out, we don't want this behaviour.
std::cout << copy.back() << " ";
copy.pop_back();
}
}
void printListOfListsOfFloats(const std::list<std::list<float>> &data) {
std::list<std::list<float>> copy = data;
while(!copy.empty()) {
printList(copy.back());
copy.pop_back();
std::cout << "\n";
}
}
int main() {
std::ifstream stream("/Users/fadi/code.dat");
std::list<std::list<float>> data;
std::string line;
while (1 == 1) {
std::getline(stream, line);
if (stream.fail()) break;
std::list<float> tmp = readNumberListFromLine(line);
if (!tmp.empty()) { data.push_front(tmp); }
}
printListOfListsOfFloats(data);
}
标准库中没有函数std::get_line。每个数据集之间是否都有一个空行?另外,每行的列数是否相同?很抱歉,getlineno行与行之间没有空格,我必须添加\n以在此处打断它们。每行有3个可能的重复数字,我们也可以使用数字数组来概括此解决方案,而不是硬编码反序列化数字1、数字2和数字3。尝试读取整数并将其放入向量或列表中,直到流中没有整数为止,然后读取EaterRight是否值得拥有两个eater变量,并检查它们是否等于预期的和。多检查一点错误不会有什么坏处。@user9335240我已经更新了问题。不幸的是,在同一个文件中还有一些其他字符串,这段代码似乎不适合处理这些字符串together@Eric您是否考虑过使用正则表达式筛选那些不符合该模式的记录?再一次请发布您的文件输入和代码。@Eric我已将编辑回滚到您的Q,因为它使此答案无效。如果你的文件中有更多的内容,你应该问一个新的问题,如果你不关心它,你应该如何读入它,或者忽略它,这样你就可以得到你需要阅读的数字行。
char eater; // this is to consume the ( and ) on each line
int number1, number2, number3;
std::ifstream fin("some_file_name.txt");
while (fin >> eater >> number1 >> number2 >> number3 >> eater) // will stop when it can't read anymore
{
// do something with the numbers
} // loop back and read the next line
std::list<float> readNumberListFromLine(const std::string &line) {
std::stringstream stream(line);
std::list<float> nums;
char chr = 0;
// Wait for a "(" token.
while(1 == 1) {
stream >> chr;
// If failed to read a character, it means eof
if (stream.fail()) break;
if (chr == '(') break;
}
// Clear the stream state, to clear the "fail" bit, to allow reading more while we
// check on this state
stream.clear();
while(1 == 1) {
float num;
stream >> num;
// If failed to read a number, stream of numbers have stopped, don't read numbers more.
if (stream.fail()) { break; }
nums.push_front(num);
}
stream.clear();
// This part shouldn't be like that, DRY principle says "Don't repeat yourself"
// This should be in a function because it is a repeat of the first loop
// But this would have templates and things that aren't simple
while(1 == 1) {
stream >> chr;
if (stream.fail()) return std::list<float>();
if (chr == ')') break;
}
return nums;
}
void printList(const std::list<float> &list) {
// We don't want pop to affect the original
std::list<float> copy = list;
while (!copy.empty()) {
// We pushed on the front, so when we pop, pop from back, push/pop is a LIFO mechanism
// Last-in-first-out, we don't want this behaviour.
std::cout << copy.back() << " ";
copy.pop_back();
}
}
void printListOfListsOfFloats(const std::list<std::list<float>> &data) {
std::list<std::list<float>> copy = data;
while(!copy.empty()) {
printList(copy.back());
copy.pop_back();
std::cout << "\n";
}
}
int main() {
std::ifstream stream("/Users/fadi/code.dat");
std::list<std::list<float>> data;
std::string line;
while (1 == 1) {
std::getline(stream, line);
if (stream.fail()) break;
std::list<float> tmp = readNumberListFromLine(line);
if (!tmp.empty()) { data.push_front(tmp); }
}
printListOfListsOfFloats(data);
}