我需要读取文本文件的内容并将值存储到变量中。考虑这个简单的文件:
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
中?还是我应该考虑一个更简单的选择?
答案 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;'