【问题标题】:Reading from text file to structure从文本文件读取到结构
【发布时间】:2016-10-21 12:57:09
【问题描述】:

首先,我想解释一下我想要做什么。所以,我有一个包含 10 个名称的文本文件,后面跟着它们的点。我正在尝试使用函数(void)创建结构并从文件中读取信息。这就是我的代码和文本文件:

代码:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

void read(struct laLiga t[]) {
    ifstream infile("info.txt");
    int i = 0;
    while(infile >> t.team[i] >> t.points[i]) {
        infile.get(t.team);
        infile >> t.points;
        i++;
    }
}

struct laLiga {
    char team[50];
    int points;
};

int main() {
    struct laLiga t[10];
    read(t);
    return 0;
}

文本文件:

Athletic Bilbao  15
Atletico Madrid  18
Barcelona  16
Alaves  10
Las Palmas  12
Real Madrid  18
Real Sociedad  10
Sevilla  17
Eibar  11
Villarreal  16

【问题讨论】:

  • 你的问题到底是什么?

标签: c++ c++11


【解决方案1】:

首先,您需要在read函数中使用它之前定义结构

其次,在read 函数中,变量t 是一个数组,而不是它的成员。所以你应该使用t[i].teamt[i].points

第三,您已经在循环条件中使用&gt;&gt; 运算符从文件中读取数据。您不应该在循环内再次阅读

第四,您要读取的输入文件实际上比您想象的更难解析。那是因为您可以同时拥有没有 的名称,其中包含空格。输入流的get 函数和输入运算符&gt;&gt; 都以空格分隔。您可能应该 read the whole line 然后在最后一个空格处拆分它。

最后,实际上我应该写答案的一个原因是您实际上并没有提出问题,或者告诉我们您的代码有什么问题。以后有问题请read about how to ask good questions

【讨论】:

  • 感谢您的帮助。很抱歉在发布问题之前没有阅读重要信息。
【解决方案2】:

您可以使用std::vector 让事情变得更简单:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <iomanip>

using namespace std;

auto file_text = 
R"(Athletic Bilbao  15
Atletico Madrid  18
Barcelona  16
Alaves  10
Las Palmas  12
Real Madrid  18
Real Sociedad  10
Sevilla  17
Eibar  11
Villarreal  16)";

struct laLiga {
    std::string team;
    int points;
};

void read(std::vector<laLiga>& t) {
    //ifstream infile("info.txt"); // would also work
    std::stringstream infile{file_text};
    while(infile) {
        laLiga laliga{};
        std::string partial_team_name{};
        while(!(infile >> laliga.points)) { // keep going until we get the points
            infile.clear(); // we could not read points, infile stream now in error; clearing to continue
            if(infile >> partial_team_name) // maybe the next string is part of a team name
                laliga.team += (laliga.team.empty() ? "" : " ") + partial_team_name; // add to team name with space if there was something already in there
            else
                return; // no points, no team, we're done
        }
        t.push_back(laliga); // after we get the points we can add the team
    }
}

int main() {
    std::vector<laLiga> t;
    read(t);
    for(auto i : t) {
        std::cout << std::setw(30) << i.team;
        std::cout << std::setw(10) << i.points << '\n';
    }
    return 0;
}

输出:

       Athletic Bilbao        15
       Atletico Madrid        18
             Barcelona        16
                Alaves        10
            Las Palmas        12
           Real Madrid        18
         Real Sociedad        10
               Sevilla        17
                 Eibar        11
            Villarreal        16

live demo

【讨论】:

  • 嘿,谢谢你的好建议,我说的是向量。一切看起来都不错,但我需要更多解释。首先,我不明白这种情况是如何工作的:“!(infile >> laliga.points)”。其次,我不明白为什么我们需要清除文件以及进行哪些更改。最后,你能解释一下这是如何工作的:' laliga.team.empty() 吗? "" : " " '
  • !(infile &gt;&gt; laliga.points) 表示从infile 读取到points。如果infile &gt;&gt; laliga.points 失败,那么它将评估为false!(infile &gt;&gt; laliga.points) 将是 true 如果我们无法读取积分,那么程序将继续尝试读取团队名称的一部分。
  • infile.clear(); 保持 infile 不变,除了标志。标志被清除。在infile &gt;&gt; laliga.points 失败(无法读取点)后,我们必须清除infile 的错误标志才能再次尝试读取。
  • (laliga.team.empty() ? "" : " ")ternary conditional operator。如果还没有团队名称,则返回""(无空格),否则返回" "(一个空格)。因此,如果laliga.team 为空,则添加partial_team_name,否则添加" " + partial_team_name
【解决方案3】:

如果您想在文本文件中读取或写入结构,那么最好使用 ifstream read() 函数和 ofstream write() 函数。以下是如何使用它们。

#include <iostream>
#include <fstream>
#include <cstring> // for strncpy()

using namespace std;

struct laLiga {
    char team[50];
    int points;
};

int main()
{
struct laLiga t;

strncpy(t.team,"Some Name",sizeof("Some Name"));
t.points = 100;

//do this for writing  a complete struct to a text file at once
ofstream output("info.txt");
output.write(reinterpret_cast<char*>(&t),sizeof(t));
output.close();

//do this for reading a complete struct from a text file at once

struct laLiga T;

ifstream input("info.txt");
input.read(reinterpret_cast<char*>(&T),sizeof(T));
input.close();

//now T will hold both the name and points fields from the text file without doing it individually

cout << "Name = " <<T.team << endl;
cout << "Points = " << T.points << endl;

return 0;
}

输出(控制台)

   Name = Some Name

   Points = 100

read()write() 函数的第一个参数应该是char* 这就是为什么我们使用reinterpret_cast 将完整的结构转换为字节序列然后写入文件的原因。 这样做的唯一缺点是文本文件在 windows 中打开时将无法读取,因为它不是普通文本,但读写会容易得多。

【讨论】:

    猜你喜欢
    • 2013-12-25
    • 2017-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-06
    • 1970-01-01
    • 1970-01-01
    • 2019-12-26
    相关资源
    最近更新 更多