Таким образом, в основном я должен сделать базу данных, как приложение на 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, например, с дублированными / скремблированными данными).
Ваш вывод правильный, но ваш ввод неправильный. Вы не должны использовать 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
}
}
редактировать: Некоторые исправления в объяснении оригинального кода.