C++ 逐行读取文件,然后使用分隔符分割每一行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3910326/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 14:03:11  来源:igfitidea点击:

C++ Read file line by line then split each line using the delimiter

c++readfile

提问by sikas

I want to read a txt file line by line and after reading each line, I want to split the line according to the tab "\t" and add each part to an element in a struct.

我想逐行读取 txt 文件,在读取每一行后,我想根据选项卡“\t”拆分该行并将每个部分添加到结构中的元素中。

my struct is 1*char and 2*int

我的结构是 1*char 和 2*int

struct myStruct
{
    char chr;
    int v1;
    int v2;
}

where chr can contain more than one character.

其中 chr 可以包含多个字符。

A line should be something like:

一行应该是这样的:

randomstring TAB number TAB number NL

回答by Martin York

Try:
Note: if chr can contain more than 1 character then use a string to represent it.

尝试:
注意:如果 chr 可以包含 1 个以上的字符,则使用字符串来表示它。

std::ifstream file("plop");
std::string   line;

while(std::getline(file, line))
{
    std::stringstream   linestream(line);
    std::string         data;
    int                 val1;
    int                 val2;

    // If you have truly tab delimited data use getline() with third parameter.
    // If your data is just white space separated data
    // then the operator >> will do (it reads a space separated word into a string).
    std::getline(linestream, data, '\t');  // read up-to the first tab (discard tab).

    // Read the integers using the operator >>
    linestream >> val1 >> val2;
}

回答by CashCow

Unless you intend to use this struct for C as well, I would replace the intended char* with std::string.

除非您也打算将此结构用于 C,否则我会将预期的 char* 替换为 std::string。

Next, as I intend to be able to read it from a stream I would write the following function:

接下来,由于我打算能够从流中读取它,我将编写以下函数:

std::istream & operator>>( std::istream & is, myStruct & my )
{
    if( std::getline(is, my.str, '\t') )
       return is >> my.v1 >> my.v2;
}

with str as the std::string member. This writes into your struct, using tab as the first delimiter and then any white-space delimiter will do before the next two integers. (You can force it to use tab).

将 str 作为 std::string 成员。这将写入您的结构,使用制表符作为第一个分隔符,然后任何空白分隔符都将在接下来的两个整数之前执行。(您可以强制它使用制表符)。

To read line by line you can either continue reading these, or read the line first into a string then put the string into an istringstream and call the above.

要逐行阅读,您可以继续阅读这些内容,也可以先将该行读入一个字符串,然后将该字符串放入一个 istringstream 中并调用上述内容。

You will need to decide how to handle failed reads. Any failed read above would leave the stream in a failed state.

您需要决定如何处理失败的读取。上面任何失败的读取都会使流处于失败状态。

回答by flownt

std::ifstream in("fname");
while(in){
    std::string line;
    std::getline(in,line);
    size_t lasttab=line.find_last_of('\t');
    size_t firsttab=line.find_last_of('\t',lasttab-1);
    mystruct data;
    data.chr=line.substr(0,firsttab).c_str();
    data.v1=atoi(line.substr(firsttab,lasttab).c_str());
    data.v2=atoi(line.substr(lasttab).c_str());
}

回答by vallismortis

I had some difficulty following some of the suggestions here, so I'm posting a complete example of overloading both input and output operators for a struct over a tab-delimited file. As a bonus, it also takes the input either from stdinor from a file supplied via the command arguments.

我在遵循此处的一些建议时遇到了一些困难,因此我发布了一个完整的示例,用于在制表符分隔的文件上为结构重载输入和输出运算符。作为奖励,它还stdin从通过命令参数提供的文件中获取输入或从文件中获取输入。

I believe this is about as simple as it gets while adhering to the semantics of the operators.

我相信在遵守运算符的语义的同时,这很简单。



pairwise.h

成对.h

#ifndef PAIRWISE_VALUE
#define PAIRWISE_VALUE

#include <string>
#include <iostream>

struct PairwiseValue
{
    std::string labelA;
    std::string labelB;
    float value;
};

std::ostream& operator<<(std::ostream& os, const PairwiseValue& p);

std::istream& operator>>(std::istream& is, PairwiseValue& p);

#endif


pairwise.cc

成对.cc

#include "pairwise.h"

std::ostream& operator<<(std::ostream& os, const PairwiseValue& p)
{
    os << p.labelA << '\t' << p.labelB << '\t' << p.value << std::endl;
    return os;
}

std::istream& operator>>(std::istream& is, PairwiseValue& p)
{
    PairwiseValue pv;

    if ((is >> pv.labelA >> pv.labelB >> pv.value))
    {
        p = pv;
    }

    return is;
}


test.cc

测试.cc

#include <fstream>
#include "pairwise.h"

int main(const int argc, const char* argv[])
{
    std::ios_base::sync_with_stdio(false); // disable synch with stdio (enables input buffering)

    std::string ifilename;
    if (argc == 2)
    {
        ifilename = argv[1];
    }

    const bool use_stdin = ifilename.empty();
    std::ifstream ifs;
    if (!use_stdin)
    {
        ifs.open(ifilename);

        if (!ifs)
        {
            std::cerr << "Error opening input file: " << ifilename << std::endl;
            return 1;
        }
    }

    std::istream& is = ifs.is_open() ? static_cast<std::istream&>(ifs) : std::cin;

    PairwiseValue pv;

    while (is >> pv)
    {
        std::cout << pv;
    }

    return 0;
}


Compiling

编译

g++ -c pairwise.cc test.cc
g++ -o test pairwise.o test.o

Usage

用法

./test myvector.tsv
cat myvector.tsv | ./test