【问题标题】:C++ file output duplicated [closed]C ++文件输出重复[关闭]
【发布时间】:2014-07-19 00:22:48
【问题描述】:

所以基本上我应该在 C++ 中制作一个类似应用程序的数据库。我遇到的问题是当我尝试从我创建的 .txt 文件中保存/读取时。 类定义和输出函数:

文件:table.h

#ifndef TABLE_H__
#define TABLE_H__

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include<functional>
#include<cstdio>

using namespace std;

class tableColumn
{
public:
    string colName;
    vector<string> tableCol;

    tableColumn() {};
    ~tableColumn() {};

    string getColName() { return colName; }
    void setColName(string);
    int getColSize() { return tableCol.size(); }

};


void tableColumn::setColName(string a)
{
    colName = a;
}

class tableMatrix
{
private:
    vector<tableColumn> table;
    string tableName;
public:
    tableMatrix() {};
    ~tableMatrix() {};

    string getTableName() { return tableName; }
    void setTableName(string);

    void saveToFile(string);
    void readFromFile(string);
};


void tableMatrix::saveToFile(string tableFileName)
{
    string aux;
    aux += tableFileName;
    aux += ".txt";

    ofstream out(aux.c_str());

    out << tableName << endl;
    out << table.at(1).getColSize() << endl;
    out << table.size() << endl;

    for (int i = 0; i < (int)table.size(); i++)
    {
        out << table.at(i).colName<<endl;
        for (int j = 0; j < (int)table.at(i).tableCol.size(); j++)
        {
            out << table.at(i).tableCol.at(j) << endl;
        }
    }
    out.close();
}

void tableMatrix::readFromFile(string tableFileName)
{
    string aux,element,space;
    int rows, cols;
    aux += tableFileName;
    aux += ".txt";

    ifstream in(aux.c_str());
    tableColumn auxc;

    getline(in, tableName);
    in >> rows;
    in >> cols;

    for (int i = 0; i < cols; i++)
    {
        in >> auxc.colName;
        for (int j = 0; j < rows; j++)
        {
            in >> element;
            auxc.tableCol.push_back(element);
        }
        table.push_back(auxc);
        auxc.~tableColumn();
    }
    in.close();
}

#endif

文件:数据库.h

#ifndef DATABASE_H__
#define DATABASE_H__

#include<iostream>
#include<fstream>
#include<vector>
#include<algorithm>
#include<string>
#include"table.h"
#include<cstdio>

using namespace std;

class database
{
private:
    vector<tableMatrix> db;
public:
    database() {};
    ~database() {};

    void saveToFile();
    void readFromFile();
};


void database::saveToFile()
{

    ofstream out("tablenames.txt");

    for (int i = 0; i < (int)db.size(); i++)
    {
        out << db.at(i).getTableName() << endl;
    }
    out.close();

    vector<string> filenames;
    string aux;

    for (int i = 0; i < (int)db.size(); i++)
    {
        aux = db.at(i).getTableName();
        filenames.push_back(aux);
    }
    for (int i = 0; i < (int)db.size(); i++)
    {
        db.at(i).saveToFile(filenames.at(i));
    }
}

void database::readFromFile()
{
    vector<string>filenames;
    string aux;
    ifstream in("tablenames.txt");
    tableMatrix auxt;

    while (!in.eof())
    {
        in >> aux;
        filenames.push_back(aux);
    }
    for (int i = 0; i < (int)filenames.size(); i++)
    {
        auxt.readFromFile(filenames.at(i));
        db.push_back(auxt);
    }
    in.close();
}

#endif

main.cpp:

#include "stdafx.h"
#include<iostream>
#include<fstream>
#include"database.h"
#include<sstream>
#include<Windows.h>
#include<conio.h>
#include<vector>

using namespace std;

int main()
{
    database A;
    A.readFromFile();
    A.saveToFile();

    return 0;
}

文件:tablenames.txt

aaa
asa2

文件:aaa.txt

aaa
3
2
col1
1
2
3
col2
4
5
6

文件:asa2.txt

asa2
3
2
col1
1
2
3
col2
4
5
67

基本上我想创建一个包含所有表名的 txt 文件 (tablenames.txt),然后为每个表创建一个包含其名称和列数据的 txt 文件。但是,当我尝试运行它时,它会复制我在 tablenames.txt 中的最后一个条目,并且会通过添加额外的列和/或行来弄乱我的表数据。

例如,tablenames.txt : ramdomname1, ramdomname2 变为:ramdomname1,ramdomname2,ramdomname2。其他表格文件的处理方式相同,只是它的规模更大(例如,重复/加扰数据时,2 行变为 10 行)。

【问题讨论】:

  • 你的问题实际上是?
  • 请发布SSCCE 和您的实际问题。
  • 问题:问题是什么以及如何“修复”它,以便它完成我想要它做的事情。这可能很明显,但我看不到。
  • 我建议调试您的程序,逐行逐行查看实际发生的情况。也可能相关while (!in.eof())
  • 真的很抱歉,只是我赶时间,项目比问题大得多。用完整的细节编辑了我的帖子。现在应该可以编译了。

标签: c++ file input output duplicate-data


【解决方案1】:

你的输出是正确的,但你的输入是错误的。你不应该像这样使用eof。惯用的循环是这样的:

while (in >> aux)
{
    filenames.push_back(aux);
}

查看过去数以千计的有关在循环中使用 C++ 流的 Stack Overflow 问题和答案。

让我们再看看你的原始代码:

while (!in.eof())
{
    in >> aux;
    filenames.push_back(aux);
}

这里发生的是遇到EOF时,还没有发生错误只有在读操作实际遇到EOF时才设置EOF标志,所以循环条件仍然成立。以下对operator&gt;&gt; 的调用确实将流设置为错误状态EOF,但为时已晚。该操作使aux 保持不变,即具有与以前相同的值。然后将该未修改的值再次推回向量。之后再次检查循环条件,最终失败(因为流处于错误状态)

事实上,为了更稳健的方法,使用独立的std::getline 函数并检查每个表名的正确性(例如,不允许的字符,如空格或制表符):

std::string line;
while (std::getline(in, line))
{
    if (isCorrect(line))
    {
        filenames.push_back(line);
    }
    else
    {
        // error handling
    }
}

编辑:对原代码解释的一些修正。

【讨论】:

  • auxc.~tableColumn();,它使我的系统上的程序段错误,以及标题中的方法定义,以及标题中的using namespace,也许还有main.cpp开头的窗口主义(那是...好吧也许)。
  • @didierc:其实代码还可以改进很多。我也不喜欢 C 风格的强制转换以及向量迭代没有使用迭代器这一事实。
  • 是的,我想是的。这是编写循环的另一种方式:while (in &gt;&gt; aux &amp;&amp; in.good()) { /* input check */ } // io error handling.
  • 我明白了,非常感谢您的解释,非常有帮助!自从您提到它后,我只有一个问题:使用演员表有什么问题?如果我删除那些我会收到警告(这就是他们首先出现的原因)。
  • @bf16:C 样式转换仅存在于 C 兼容性。在 C++ 中,您使用几种特定类型转换中的一种。在这种情况下,static_cast&lt;int&gt;(db.size()) 就可以了。然而,迭代容器的惯用方法是使用迭代器,这样问题就完全消失了。在这里查看快速概览:en.wikipedia.org/wiki/Iterator#C.2B.2B
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-13
  • 1970-01-01
相关资源
最近更新 更多