分隔文件的基本方法是将整行读入string,然后从该行创建一个stringstream,并使用分隔符循环调用getline的字符串流(此处为'|')将值分隔到字段中。
(这样就不需要提前知道字段的数量——如果没有stringstream,您必须将读取的字段限制为使用getline 或getline 的字段数,将愉快地从下一个开始读取数据行)
下面的示例只是将输入文件的每个字段读入string,但根据您的需要,您可能需要额外的转换(例如stol 等)将各个字段转换为int 或double(留给你)。
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <limits>
using namespace std;
int main (int argc, char **argv) {
string line;
if (argc < 2) {
cerr << "error: usage, program <filename>\n";
return 1;
}
ifstream f (argv[1]); /* open file */
if (!f.is_open()) { /* validate file open for reading */
perror (("error while opening file " + string(argv[1])).c_str());
return 1;
}
while (getline (f, line)) { /* read each line */
string val; /* string to hold value */
stringstream s (line); /* stringstream to parse fields */
/* output original line */
cout << "line: " << line << "\n\n";
/* skip 1st delim */
s.ignore(numeric_limits<streamsize>::max(), '|');
while (getline (s, val, '|')) /* for each field */
cout << " value: " << val << '\n'; /* output each field value */
cout << '\n';
}
}
输入文件示例
$ cat dat/fields.txt
| 1 | Joe | marbles | 1.25 |
| 2 | Mike | jacks | 13.49 |
| 3 | Jill | pail | 4.50 |
使用/输出示例
$ ./bin/iostream_strstream_fields dat/fields.txt
line: | 1 | Joe | marbles | 1.25 |
value: 1
value: Joe
value: marbles
value: 1.25
line: | 2 | Mike | jacks | 13.49 |
value: 2
value: Mike
value: jacks
value: 13.49
line: | 3 | Jill | pail | 4.50 |
value: 3
value: Jill
value: pail
value: 4.50
查看一下,如果您还有其他问题,请告诉我。
用 C 重写 32 年的操作系统
由于您尝试在一个 32 年历史的操作系统上使用仍然无法识别的 C++ 编译器进行编译(您的原始问题中没有指定任何一个),您可能会更好地使用 C 编写您的解析例程。为什么? C++ 标准在当时是非常无定形的。与今天的 C++ 相比,它更像是 C 的超集。在当时的 Turbo C 和 Borland C++ 编译器中,所有包含的文件仍然使用 C 头文件包含格式(在头名称的末尾包含 '.h',例如 #include <string.h>)这解释了你的“找不到标题”问题。
另一方面,C 更接近于今天可用的。尽管它经历了几次标准修订,但当时和现在可用的基本功能是相同的。在 C++ 代码上运行 DOS 3.2 的任何内容上,以下代码都有更好的编译机会。
#include <stdio.h>
#include <string.h>
#define FLDSZ 32 /* maximum file size for name and product */
#define MAXC 256 /* maximum length for line (including '\0') */
int main (int argc, char **argv) {
char buf[MAXC] = ""; /* buffer to hold each line */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
while (fgets (buf, MAXC, fp)) {
int id; /* id from file */
char name[FLDSZ] = "", /* name */
product[FLDSZ] = ""; /* product */
float price; /* price */
size_t len = strlen (buf); /* length of string in buffer */
if (len == MAXC - 1 && buf[len - 1] != '\n') { /* check it fit */
fputs ("error: line too long.\n", stderr);
return 1;
}
if (sscanf (buf, "|%d | %31s | %31s | %f", /* parse fields */
&id, name, product, &price) != 4) {
fputs ("error: failed to parse line.\n", stderr);
continue;
}
/* output parsed fields */
printf ("%3d %-10s %-10s %.2f\n", id, name, product, price);
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
return 0;
}
(程序期望数据文件名作为第一个参数,或者如果没有给出参数,它将从stdin读取)
使用/输出示例
$ ./bin/fieldparse ~/dev/src-cpp/tmp/dat/fields.txt
1 Joe marbles 1.25
2 Mike jacks 13.49
3 Jill pail 4.50
我只能告诉你试一试,然后告诉我会发生什么。