首页 > 解决方案 > 如何从两个分隔符之间的文件中提取数据或读取数据--> '|' 在 C++ 中使用 getline 函数?

问题描述

我已经在文件中的分隔符之间安排了数据。我想在一行中从一个特定点读取到另一个点。它看起来像这样:| 没有。姓名。| 产品。| 价格。| 我想一次读取一个数据。由这些分隔符划分的每个部分都包含一个或多个音节,即一个或几个单词。我怎么读这个?

标签: c++

解决方案


分隔文件的基本方法是将整行读入 a ,然后从该行string创建 a并循环使用分隔符(此处)调用 stringstream 以将值分隔到字段中。stringstreamgetline'|'

(这种方式不需要提前知道字段的数量——没有stringstream你必须限制你对字段的读取到使用的数量,getline或者很getline乐意从下一行开始读取数据)

下面的示例只是将输入文件的每个字段读入 a string,但根据您的需要,您可能需要额外的转换,(例如stol等)将各个字段转换为intor 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

我能告诉你的就是试一试,让我知道会发生什么。


推荐阅读