逐行读取用户定义的文本资源文件

时间:2019-01-25 02:06:51

标签: c++ resources scanf

我需要读取文本文件的内容并将值存储到变量中。考虑这个简单的文件:

2
-0.5    -0.5     0.0
 0.5    -0.5     0.0

在指定其文件名时(因此不使用资源),我可以这样处理fscanf_s

FILE *pFile;
fopen_s(&pFile, filename.c_str(), "r");

fscanf_s(pFile, "%d", &nPoints);
points = new Vec3[nPoints];

for (int n = 0; n < nPoints; ++n)
    fscanf_s(pFile, "%lf %lf %lf", &points[n][0], &points[n][1], &points[n][2]);

fclose(pFile);

并将数据保存到两个向量,每个向量具有三个值。

现在,我想做同样的事情,但是要使用一个包含在用户定义资源中的文件。首先,我遵循this example将数据加载到缓冲区中。问题是我不知道如何使用此缓冲区检索数据并以类似方式保存数据。我尝试使用sscanf_s函数:

sscanf_s(buffer, "%d", &nPoints);
points = new Vec3[nPoints];

for (int n = 0; n < nPoints; ++n) {
    sscanf_s(buffer, "%lf %lf %lf", &points[n][0], &points[n][1], &points[n][2]);
}

但是它似乎不像我预期的那样工作。点数已正确读取到nPoints变量中,但是两个向量最终都具有值2,-0.5,-0.5。

如何将缓冲区中的值保存到Vec3中?还是我应该考虑一个更简单的选择?

1 个答案:

答案 0 :(得分:1)

使用sscanf_s()时,您每次都传递相同的buffer指针,因此它会不断从相同的2值中重新读取。

每次读取后,您都需要使指针前进。 sscanf_f()的返回值是读取的个字段的数量,但是您需要消耗的个字符的数量,您可以使用{{1 }}格式说明符,例如:

%n

一个更好的选择是使用C ++样式I / O而不是C样式I / O。例如,您可以将char *ptr = buffer; int consumed; sscanf_s(ptr, "%d%n", &nPoints, &consumed); ptr += consumed; points = new Vec3[nPoints]; for (int n = 0; n < nPoints; ++n) { sscanf_s(ptr, "%lf %lf %lf%n", &points[n][0], &points[n][1], &points[n][2], &consumed); ptr += consumed; } 数据分配给std::istringstream,然后从该 1 中读取,例如:

buffer

1:要从文件中读取,只需将#include <sstream> std::istringstream iss(buffer); iss >> nPoints; points = new Vec3[nPoints]; for (int n = 0; n < nPoints; ++n) { iss >> points[n][0] >> points[n][1] >> points[n][2]; } 替换为std::ifstream

或者,如果您希望避免分配std::istringstream数据的std::string副本的开销,则可以write a custom std::basic_streambuf class(或找到第三方实现)来从您的buffer(甚至更好,直接来自原始资源),例如:

buffer

一旦切换为使用C ++ I / O流,您就可以通过利用C ++标准库中的容器和算法来进一步简化事情,例如:

#include <iostream>

SomeCharArrayStreamBuf buf(buffer, size);
std::istream is(&buf);

is >> nPoints;
points = new Vec3[nPoints];

for (int n = 0; n < nPoints; ++n) {
    is >> points[n][0] >> points[n][1] >> points[n][2];
}

#include <vector>

std::vector<Vec3> points; // <-- instead of 'Vec3 *pointers;'