通过 fstream 创建结构

Posted

技术标签:

【中文标题】通过 fstream 创建结构【英文标题】:Creating Structures via fstream 【发布时间】:2009-07-24 16:30:46 【问题描述】:

C++ Primer Plus 中的一个练习是让我使用 fstream 打开一个 txt 文件并将数据输入到结构中然后输出。 txt 文件的第一行是“捐助者”的数量。我似乎遇到的问题是(我认为)当我使用“inFile >> value;”时检索数字然后通过new分配结构,它需要一个int并得到一个字符串?它是否正确?我应该做些什么不同的事情?

//ch6 p278 exercise #9
#include <iostream>
#include <cstring>
#include <fstream>
#include <cstdlib>
using namespace std;
const int SIZE = 60;
struct contributions

    char name[20];
    double dollars;
;

char filename[20];
string donors;
bool donated;

int main()

    char filename[SIZE];
    cout << "Enter name of file to scan: ";
    cin >> filename;
    fstream inFile;
    inFile.open(filename);
    if(!inFile.is_open())
    
        cout << "Could not open the file " << filename << endl;
        cout << "Program terminating.\n";
        exit(EXIT_FAILURE);
    
    inFile >> donors;
    contributions * ptr = new contributions[donors];
    for(int h = 0; h < donors; h++)
    
        inFile >> ptr[h].name);
        inFile >> ptr[h].dollars);
    
//BEGIN OUTPUT OF STRUCTURES
    cout << "GRAND PATRONS:\n";
    for(int i = 0; i < donors; i++)
   
       if(ptr[i].dollars >= 10000)
       
           cout << ptr[i].name << " donated " << ptr[i].dollars << endl;
           donated = true;
       
   
   if (!donated) cout << "none.\n";
   donated = false;
   cout << "PATRONS:\n";
   for(int i=0; i < donors; i++)
   
       if(ptr[i].dollars < 10000)
       
           cout << ptr[i].name << " donated " << ptr[i].dollars << endl;
           donated = true;
       
   
   if (!donated) cout << "none.\n";
   delete ptr;
    return 0;

【问题讨论】:

与手头的问题分开,因为你已经使用new的数组版本来分配ptr,你将需要使用delete的数组版本,比如这个:delete[] ptr; 【参考方案1】:

我应该做些什么不同的事情?

好吧,如果代码基于 C++ Primer Plus 教给您的内容,请使用不同的教科书。我不想侮辱你,但代码真的很糟糕。例如,本书是否涵盖了 std::string 类?

我会建议把它扔掉,并获得 Koenig 和 Moo(最初的 C++ 团队的两个成员)的 Accelerated C++,它将教你现代、优秀、惯用的 C++。

【讨论】:

一点也不侮辱。该代码是我自己的代码的混搭,并从书中的示例代码中提取了一些想法。它被覆盖的字符串,但我觉得好像我错过了一些东西。 Vector 也被提及,在 280 页中,它还没有提及这一点。现在看看 Accelerated C++... 原则上我支持这一点,除了许多人发现“加速 C++”的学习曲线太陡峭的事实。对于那些我推荐“C++ Primer”bay Lippman/Lajoie/Moo。 (注意:没有“Plus”,但至少坚持第 3 版,Barbara Moo 加入了团队!) 我读过 Lippmann 的“C++ Primer”,当它第一次出版时(很久以前),我认为它一直在讲最明显的事情——除了第一版,我没有读过任何东西尽管。也许我不是 C++ 教程的理想测试平台...【参考方案2】:

您肯定是正确的,我假设代码无法编译?您可以将捐助者变量更改为整数。输入流被重载以使用所有内置类型,即。 bool、double、int 等。

假设下一个值是整数,以下将起作用:

int numDonors;
inFile >> numDonors;

请注意,更改为整数也是“for”循环正常工作所必需的,您当前正在将字符串与整数进行比较,没有内置/默认行为。

编辑:我还注意到,当您删除贡献者数组时:

delete ptr;

但是,这只会清除第一个动态分配的块。删除动态分配对象数组的正确方法是:

delete [] ptr;

编辑 2: 感谢您的示例,所以它无法正常工作的原因是名称是第一个和最后一个,并且流运算符“>>”在空格上中断。所以本质上发生的是您首先尝试读取名称,流仅读取第一个名称并停止。然后你尝试读取捐赠的值,这会尝试读取姓氏作为值,并且无法转换为双精度,因此它返回 0。

【讨论】:

它现在可以编译,但是当它从文件中读取数据时,它的反馈是不正确的。 如您的打印输出不正确?我需要查看输入文件的示例以提供更多帮助。 输入:4 Sam Stone 2000 Freida Flass 100500 Tammy Tubbs 5000 Rich Raptor 55000 输出:输入要扫描的文件名:9.txt 大赞助人:无。赞助人:山姆捐赠 0 捐赠 0 捐赠 0 捐赠 0【参考方案3】:

donors 是一个字符串,您正在尝试将其用作数组大小:

string donors;
//...

inFile >> donors;
contributions * ptr = new contributions[donors];

您应该将 donors 设为 int。此外,通常最好使用std::vector&lt;&gt;,而不是手动弄乱指向原始数组的指针。看起来像这样:

std::vector<contributions> contribs;
for (...) 
  contributions contrib;
  // .. Some way read contrib from inFile
  contribs.push_back(contrib);

【讨论】:

以上是关于通过 fstream 创建结构的主要内容,如果未能解决你的问题,请参考以下文章

fstream类怎么创建和删除文件?

C++(八):fstream读写操作

C++中fstream

C++文件流的C++ 中 *fstream 操作

fstream.h是啥意思?又啥作用啊?

C++文件读写详解(ofstream,ifstream,fstream)