【问题标题】:How to extract data or read data from a file between two delimiters--> '|' using getline function in c++?如何从两个分隔符之间的文件中提取数据或读取数据--> '|'在 C++ 中使用 getline 函数?
【发布时间】:2018-05-12 02:30:39
【问题描述】:

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

【问题讨论】:

  • 你叫它。 getline(stream, token, '|') 将为您提供从开始到第一个 |、两个 |s 或最后一个 | 之间的所有内容到流的末尾。
  • 或者,更好的是,读取整行,然后使用stingstream s (line),然后使用while (getline (s, val, '|')),这样您一次读取的数据不会超过 1 行。

标签: c++


【解决方案1】:

分隔文件的基本方法是将整行读入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 &lt;string.h&gt;)这解释了你的“找不到标题”问题。

另一方面,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

我只能告诉你试一试,然后告诉我会发生什么。

【讨论】:

  • 谢谢您,先生。但问题是我的编辑器不支持某些功能,因为它无法识别头文件。你能给出其他选择吗??
  • 什么编译器? (这些都是 C++ 标准头文件。)您的编译器说什么无法识别?可以用-std=C++11 选项编译吗?
  • @VinitaKumari 我在 Linux 和 Windows7(旧 VS)上都编译过,它在两者上都编译和运行良好。我无法想象你有比 Win7 更旧的东西?
  • 不,其实我是用ms dos来写我的c++程序
  • 哦,就像 Borland C++ 时代一样?什么版本的 MSDOS?我曾经在 DOS 4.1 上使用 Borland(摆脱了 DOS 3.X 的 33M 分区限制)。你用的是什么编译器,所以我可以查一下它有什么? (哦,天哪,那是为我的带有数学协处理器的 386DX 准备的) 我能想到的唯一标题是 &lt;limits&gt; 是你的编译器找不到的东西吗?告诉我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-19
  • 2018-11-01
  • 1970-01-01
  • 2015-05-21
  • 1970-01-01
相关资源
最近更新 更多