C++程序显示debug error abort()has been called
我在写一个连接oracle数据库,读取一个表,然后删除表中赘余属性的C++程序
在vs2015上运行能显示出正确结果 但是之后会弹出debug error的信息窗口,检查后发现问题出现在LoadTable()这个函数上
我把这个函数的调用注释掉就不会出错,但我把这个函数的函数体内容全部注释掉,只留return语句,再调用时还是出错,不知道问题到底出在哪里。
下面是完整的代码
// MyC++.cpp : 定义控制台应用程序的入口点。
#include<iostream>
#include<iomanip>
#include<sstream>
#include<string>
#include<set>
#import "C:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","adoEOF")
using namespace std;
#define MAXATTRIBUTIONCOUNT 15
#define MAXELEMENTS 10
typedef struct {
string attName;
bool necessary;
}_attribute;//表属性
typedef struct _classification {
string value;
int element[MAXELEMENTS];
int elementCount;
struct _classification* next;
}_classification;//分类
//数据库操作
class CDBOperation
{
public:
CDBOperation(void);
~CDBOperation(void);
bool ConnToDB(char* ConnectionString,char* UserID,char* Password);
_RecordsetPtr ExecuteWithResSQL(const char*);//查询操作
_RecordsetPtr ExecuteWithResSQL(const string );
bool ExecuteWithoutResSQL(const char*);//增删操作
bool ExecuteWithoutResSQL(const string);
void PrintResult();//打印查询结果
private:
void PrintErrorInfo(_com_error &);
_ConnectionPtr CreateConnPtr();
_CommandPtr CreateCommPtr();
//_RecordsetPtr CreateRecsetPtr();
private:
_ConnectionPtr m_pConnection;
_CommandPtr m_pCommand;
_RecordsetPtr m_pRst;
};
/****************CDBOperation类定义***********************/
CDBOperation::CDBOperation(void)
{
CoInitialize(NULL);
m_pConnection = CreateConnPtr();
m_pCommand = CreateCommPtr();
m_pRst = nullptr;
}
CDBOperation::~CDBOperation(void)
{
m_pConnection->Close();
CoUninitialize();
}
bool CDBOperation::ConnToDB(char *ConnectionString, char* UserID, char *Password)
{
if (nullptr == m_pConnection)
{
cout << "Failed to create connection!" << endl;
return false;
}
try
{
HRESULT hr = m_pConnection->Open(ConnectionString,UserID,Password,NULL);
if (TRUE == FAILED(hr))
{
return false;
}
m_pCommand->ActiveConnection = m_pConnection;
return TRUE;
}
catch (_com_error &e)
{
PrintErrorInfo(e);
return false;
}
}
_RecordsetPtr CDBOperation::ExecuteWithResSQL(const char* sql)
{
try
{
m_pCommand->CommandText = _bstr_t(sql);
m_pRst = m_pCommand->Execute(NULL,NULL,adCmdText);
if (NULL == m_pRst)
{
cout << "查询数据库出错!" << endl;
return nullptr;
}
if (m_pRst->adoEOF)
{
cout << "表中无记录!" << endl;
return nullptr;
}
return m_pRst;
}
catch (_com_error &e)
{
PrintErrorInfo(e);
return NULL;
}
}
_RecordsetPtr CDBOperation::ExecuteWithResSQL(const string sql)
{
return ExecuteWithResSQL(sql.data());
}
bool CDBOperation::ExecuteWithoutResSQL(const char* sql)
{
if (ExecuteWithResSQL(sql))return true;
else return false;
}
bool CDBOperation::ExecuteWithoutResSQL(const string sql)
{
return ExecuteWithoutResSQL(sql.data());
}
void CDBOperation::PrintResult()
{
if (!m_pRst)
{
cout << "没有可打印的查询结果!"<<endl;
return;
}
_RecordsetPtr p = m_pRst;
_variant_t vAge, vName;
string s1 = "age";
while (!p->adoEOF)
{
vAge = p->GetCollect(_variant_t(s1.data()));
vName = p->GetCollect(_variant_t("name"));
cout << "age: " << (string)(_bstr_t)vAge << "\n";
cout << "name: " << (string)(_bstr_t)vName << endl;
p->MoveNext();
}
}
_ConnectionPtr CDBOperation::CreateConnPtr()
{
HRESULT hr;
_ConnectionPtr connPtr;
hr = connPtr.CreateInstance(__uuidof(Connection));
if (FAILED(hr) == TRUE)
{
return NULL;
}
return connPtr;
}
_CommandPtr CDBOperation::CreateCommPtr()
{
HRESULT hr;
_CommandPtr commPtr;
hr = commPtr.CreateInstance(__uuidof(Command));
if (FAILED(hr) == TRUE)
{
return NULL;
}
return commPtr;
}
void CDBOperation::PrintErrorInfo(_com_error &e)
{
cout << "Error infomation is as follows:\n";
cout << "ErrorNo: " << e.Error() << "\n";
cout << "Error Message: " << e.ErrorMessage() << "\n";
cout << "Error Source: " << (LPCTSTR)e.Source() << "\n";
cout << "Error Description: " << (LPCTSTR)e.Description() << "\n";
}
//数据库表
class Table {
friend class CDBOperation;
public:
Table();
~Table();
//bool AnalyseTable(CDBOperation, string);
bool LoadTable(CDBOperation, string);
void ShowAttribute();
void ShowTable();
//约简算法
void BlindReduct();
//显示约简后的表
void ShowReductAtrribute();
void ShowReductTable();
private:
_classification *FindClassification(const string);
void PreprocessTable(void);
private:
_attribute attribute[MAXATTRIBUTIONCOUNT];
int attriCount;//实际的属性数目
_classification *classification;
int classCount;//基本集数
};
Table::Table()
{
this->attriCount = 0;
this->classification = nullptr;
this->classCount = 0;
}
Table::~Table()
{
_classification *ptr=this->classification;
while (ptr)
{
this->classification = ptr->next;
delete ptr;
ptr = this->classification;
}
}
void Table::PreprocessTable()
{
for (int i = 0; i < this->attriCount; i++)this->attribute[i].necessary = true;
}
_classification* Table::FindClassification(const string val)
{
if (val == " ") { cout << "无效的分类!" << endl; return nullptr; }
_classification *ptr = this->classification;
while ((ptr)&&(ptr->value != val))ptr=ptr->next;
if (!ptr)
{
ptr = new _classification;
ptr->value = val;
ptr->elementCount = 0;
ptr->next = this->classification;
this->classification = ptr;
this->classCount++;
}
return ptr;
}
/*bool Table::AnalyseTable(CDBOperation dbOp, string tableName)
{
if (tableName == " ") { cout << "表名不能为空!" << endl; return false; }//表名为空
this->attriCount = 0;
for (int i = 0; i < (int)tableName.length(); i++)tableName[i] = toupper(tableName[i]);//将表名转为大写
_RecordsetPtr setPtr = dbOp.ExecuteWithResSQL("select column_name from user_tab_columns where table_name = '" + tableName + "'");
while (!setPtr->adoEOF)
{
this->attribute[attriCount].attName = (string)(_bstr_t)setPtr->GetCollect(_variant_t("COLUMN_NAME"));
this->attribute[attriCount].necessary = true;
this->attriCount++;
setPtr->MoveNext();
}
return true;
}*/
bool Table::LoadTable(CDBOperation dbOp, string tableName)
{
//表名为空
if (tableName == " ") { cout << "表名不能为空!" << endl; return false; }
this->attriCount = 0;
//将表名转为大写
for (int i = 0; i < (int)tableName.length(); i++)tableName[i] = toupper(tableName[i]);
//分析表列名
_RecordsetPtr setPtr = dbOp.ExecuteWithResSQL("select column_name from user_tab_columns where table_name = '" + tableName + "'");
if (!setPtr||setPtr->adoEOF)return false;
while (!setPtr->adoEOF)
{
this->attribute[attriCount].attName = (string)(_bstr_t)setPtr->GetCollect(_variant_t("COLUMN_NAME"));
this->attribute[attriCount].necessary = true;
this->attriCount++;
setPtr->MoveNext();
}
//查询表数据
setPtr = dbOp.ExecuteWithResSQL("select * from "+tableName);
string val="";
int number = 1;
while (!setPtr->adoEOF)
{
for (int i = 0; i < this->attriCount;i++)
val=val+ (string)(_bstr_t)setPtr->GetCollect(_variant_t(this->attribute[i].attName.data()))+" ";
_classification *ptr = this->FindClassification(val);
ptr->element[ptr->elementCount] = number;
ptr->elementCount++;
number++;
val = "";
setPtr->MoveNext();
}
return true;
}
void Table::ShowAttribute()
{
if (this->attriCount == 0) { cout << "没有可显示的列名!" ; return; }
cout << left << setw(5) << "编号";
for (int i = 0; i < this->attriCount; i++)
cout << left<<setw(15)<<this->attribute[i].attName << " ";
}
void Table::ShowTable()
{
this->ShowAttribute();
cout << endl<<endl;
if (!this->classification){cout << "没有可显示的元组!"; return;}
_classification *ptr = this->classification;
while (ptr)
{
for (int i = 0; i < ptr->elementCount; i++)
{
cout << left << setw(5) << ptr->element[i];
//读取一个分类的value并分离出每个属性的具体值
istringstream ss(ptr->value);
string val;
while (ss >> val)cout << left << setw(16) << val;
cout << endl<<endl;
}
ptr = ptr->next;
}
}
void Table::BlindReduct()
{
this->PreprocessTable();
set<string> attri;
_classification *ptr = this->classification;
for (int i = 0; i < this->attriCount; i++)//当前删除第几个属性
{
while (ptr)//删除当前属性能得到的所有分类
{
istringstream ss(ptr->value);
string val, fVal;
int count = 0;//当前添加第几个属性的值
while (ss >> val)
{
if (this->attribute[count].necessary&&count!=i)fVal = fVal + val + " ";//获得删除后的属性值集合
count++;
}
if(!fVal.empty())attri.insert(fVal);
ptr = ptr->next;
}
if (attri.size() == this->classCount)this->attribute[i].necessary = false;
attri.clear();
ptr = this->classification;
}
}
void Table::ShowReductAtrribute()
{
if (this->attriCount == 0) { cout << "没有可显示的列名!"; return; }
cout << left << setw(5) << "编号";
for (int i = 0; i < this->attriCount; i++)
if(this->attribute[i].necessary)
cout << left << setw(15) << this->attribute[i].attName << " ";
}
void Table::ShowReductTable()
{
this->ShowReductAtrribute();
cout << endl << endl;;
if (!this->classification) { cout << "没有可显示的元组!"; return; }
_classification *ptr = this->classification;
while (ptr)
{
for (int i = 0; i < ptr->elementCount; i++)
{
cout << left << setw(5) << ptr->element[i];
//读取一个分类的value并分离出每个属性的具体值
istringstream ss(ptr->value);
string val;
int count = 0;
while (ss >> val)
{
if (this->attribute[count].necessary)
cout << left << setw(16) << val;
count++;
}
cout << endl << endl;
}
ptr = ptr->next;
}
}
int main()
{
CDBOperation dbOper;
bool bConn = dbOper.ConnToDB("Provider = OraOLEDB.Oracle.1; Persist Security Info = True; Data Source = orcl","system","system");
if (false == bConn) { cout << "连接数据库出错!"; getchar(); return 0; }
else cout << "连接成功!"<<endl;
cout << "输入要约简的表名:" << endl;
string s;
cin >> s;
Table table;
//读取表数据
table.LoadTable(dbOper,s);
//未约简的表
table.ShowTable();
/cout << endl;
//盲目约简
table.BlindReduct();
//约简后的表
table.ShowReductTable();
cout << endl;
table.~Table();
dbOper.~CDBOperation();
getchar();*/
return 0;
}