C ++ файл дублируется

Таким образом, в основном я должен сделать базу данных, как приложение на 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

Файл: database.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

В основном я хочу создать текстовый файл со всеми именами таблиц (tablenames.txt) и затем текстовый файл для каждой таблицы с ее именем и данными столбца. Однако, когда я пытаюсь запустить его, он дублирует мою последнюю запись в tablenames.txt и портит данные моей таблицы, добавляя дополнительные столбцы и / или строки.

Например, tablenames.txt: ramdomname1, ramdomname2 становится: ramdomname1, ramdomname2, ramdomname2. То же самое относится и к другим файлам таблицы, за исключением того, что он делает это в большем масштабе (2 строки становятся 10, например, с дублированными / скремблированными данными).

-5

Решение

Ваш вывод правильный, но ваш ввод неправильный. Вы не должны использовать eof как это. Идиоматический цикл выглядит так:

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

Посмотрите на тысячи прошлых вопросов и ответов по переполнению стека об использовании потоков C ++ в циклах.

Давайте еще раз посмотрим на ваш оригинальный код:

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

Что здесь происходит, так это при обнаружении EOF еще не было ошибокфлаг EOF устанавливается только тогда, когда операция чтения действительно встречается с EOF, поэтому условие цикла все еще выполняется. Следующий звонок operator>> делает установите поток в состояние ошибкиEOF, но уже слишком поздно Операция уходит aux неизмененным, то есть с тем же значением, что и раньше. Это неизмененное значение затем снова возвращается к вектору. После этого условие цикла проверяется снова и, наконец, не удается (потому что поток находится в состоянии ошибки).

На самом деле, для еще более надежного подхода используйте отдельно стоящие std::getline и проверьте правильность каждого имени таблицы (например, недопустимые символы, такие как пробелы или символы табуляции):

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

редактировать: Некоторые исправления в объяснении оригинального кода.

1

Другие решения


По вопросам рекламы [email protected]