了解在 C++ 中读取 txt 文件

Understanding reading txt files in c++

本文关键字:txt 文件 读取 C++ 了解      更新时间:2023-10-16

我正在尝试理解在 c++ 中读取不同的 txt 文件格式

我目前正在尝试读取这样格式化的文件,

val1 val2 val3
val1 val2 val3
val1 val2 val3

当我读入文件然后cout其内容时,我只得到第一行,然后在最后随机0 0

我想将每个值保存到结构中自己的变量中。

我是这样做的,

struct Input{
    std::string group;
    float total_pay;
    unsigned int quantity;
    Input(std::string const& groupIn, float const& total_payIn, unsigned int const& quantityIn):
    group(groupIn),
    total_pay(total_payIn),
    quantity(quantityIn)
    {}
};
int main(){
    std::ifstream infile("input.txt");
    std::vector<Input> data;
    std::string group;
    std::string total_pay;
    std::string quantity;
    std::getline(infile,group);
    std::getline(infile,total_pay);
    std::getline(infile,quantity);
    while(infile) {
        data.push_back(Input(group,atof(total_pay.c_str()),atoi(quantity.c_str())));
        std::getline(infile,group);
        std::getline(infile,total_pay);
        std::getline(infile,quantity);
    }

    //output
    for(Input values : data) {
        std::cout << values.group << " " << values.total_pay << " " << values.quantity << 'n';
    }
    return 0;
}

以我指定的格式读取此文件的正确方法是什么?我是否需要指定转到第三个值之后的下一行?

或者这应该获取每个值并将它们放入正确的变量中?

std::getline(infile,group);
std::getline(infile,total_pay);
std::getline(infile,quantity);

您的输入处理存在许多问题。您在不需要的地方普遍使用std::getline是无济于事的。

简而言之,输入的每行验证通常使用类似于以下内容的模型完成。请注意,这要求类提供默认构造函数。我们使用输入字符串流来处理输入文件中每行输入中的单个项目。如果确定每行最多有一个,我们可以放弃每行处理,但这是一个潜在的错误的地方,所以安全总比后悔好。此处介绍的口头禅通常用于从格式化的输入文件中读取对象流(每行一个项目(时每行输入验证。

以下代码通过一些额外的部分定义结构,包括提供输入和输出流插入运算符。结果使main()中的代码更易于管理

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <iterator>
struct Input
{
    // friends not needed if the members are public, but provided here
    //  in case you ever do make them protected or private (which you should)
    friend std::istream& operator >>(std::istream& inp, Input& item);
    friend std::ostream& operator <<(std::ostream& outp, Input const& item);
    std::string group;
    float total_pay;
    unsigned int quantity;
    // default constructor. sets up zero-elements
    Input() : total_pay(), quantity()
    {
    }
    Input(std::string groupIn, float total_payIn, unsigned int quantityIn)
        : group(std::move(groupIn))
        , total_pay(total_payIn)
        , quantity(quantityIn)
    {
    }
    // you really should be using these for accessors
    std::string const& getGroup() const { return group; }
    float getTotalPay() const { return total_pay; }
    unsigned int getQuantity() const { return quantity; }
};
// global free function for extracting an Input item from an input stream
std::istream& operator >>(std::istream& inp, Input& item)
{
    return (inp >> item.group >> item.total_pay >> item.quantity);
}
// global operator for inserting to a stream
std::ostream& operator <<(std::ostream& outp, Input const& item)
{
    outp << item.getGroup() << ' '
         << item.getTotalPay() << ' '
         << item.getQuantity();
    return outp;
}
int main()
{
    std::ifstream infile("input.txt");
    if (!infile)
    {
        std::cerr << "Failed to open input file" << 'n';
        exit(EXIT_FAILURE);
    }
    // one line per item enforced.
    std::vector<Input> data;
    std::string line;
    while (std::getline(infile, line))
    {
        std::istringstream iss(line);
        Input inp;
        if (iss >> inp) // calls our extaction operator >>
            data.emplace_back(inp);
        else
            std::cerr << "Invalid input line: " << line << 'n';
    }
    // dump all of them to stdout. calls our insertion operator <<
    std::copy(data.begin(), data.end(),
              std::ostream_iterator<Input>(std::cout,"n"));
    return 0;
}

如果输入格式正确,则值如下所示:

group total quantity
group total quantity

将成功解析。相反,如果发生这种情况:

group total quantity
group quantity
group total quantity
total quantity

第二项和第四项的提取将失败,std::cerr 时将发出适当的警告。这就是使用std::istringstream中间流对象包装提取每个项目一行的原因。

祝你好运,希望它能帮助你。

检查此解决方案

它没有错误检查,但可以转换为类型

#include<iostream>
#include<sstream>
using namespace std;
int main()
{
    string line="v1 2.2 3";//lets say you read a line to this var...
    string group;
    float total_pay;
    unsigned int quantity;
    //we split the line to the 3 fields
    istringstream s(line);
    s>>group>>total_pay>>quantity;
    //print for test
    cout<<group<<endl<<total_pay<<endl<<quantity<<endl;
    return 0;
}