【问题标题】:The final value of my database corrupts after quick sort [closed]快速排序后我的数据库的最终值损坏[关闭]
【发布时间】:2012-12-05 20:27:13
【问题描述】:

所以我设法编写了一个程序,将 OpAmp 数据存储在一个小型数据库(10 条数据)中,一切似乎都很好,直到我执行快速排序,按 Slew Rate 升序排序。当我这样做时,我的数据库中的最后一条数据作为一系列与输入的数据无关的符号返回。这不会在按名称快速排序时发生。有人知道出了什么问题吗?这是我的代码...

//File: Task1.cpp
//Title: Structured Programming in C++
//Created: 05/12/2012
//Author: Nicole ...
//ID Number: ...
//Accompanying Files: database.txt
//Description:A program which allows 
#include <iostream>
#include <fstream>
#include <string.h>
using namespace std;

// the format of each of the elements in the database
struct OpAmps {
  char Name[20];  // the name of the op-amp (e.g. "741")
  unsigned int PinCount;  // the number of pins in the package
  double SlewRate;  // the slew rate in volts per microsecond
};

// the length of the fixed array to be used for database - must be at least one
// and no greater the maximum value allowed in an unsigned long (see the file limits.h)
#define DATABASE_MAX 10

// file used for the database
#define DATABASE_FILENAME "database.txt"

// function prototypes
void Enter(OpAmps&, unsigned long&);
void Save(OpAmps[], unsigned long);
void Load(OpAmps[], unsigned long&);
void Sort(OpAmps[], unsigned long);
void Display(OpAmps[], unsigned long);
void QuickSortName (OpAmps[], unsigned long);
void QuickSortSlewRate (OpAmps[], unsigned long);

// Control the entering, saving, loading, sorting and displaying of elements in the database
// Arguments: None
// Returns: 0 on completion
int main()
{
  OpAmps OpAmp[DATABASE_MAX];   // the database
  unsigned long database_length = 0;  // the number of elements in the database
  char UserInput;

  // loop until the user wishes to exit
  while (1) {

    // show the menu of options
    cout << endl;
    cout << "Op-amp database menu" << endl;
    cout << "--------------------" << endl;
    cout << "1. Enter a new op-amp into the database" << endl;
    cout << "2. Save the database to disk" << endl;
    cout << "3. Load the database from disk" << endl;
    cout << "4. Sort the database" << endl;
    cout << "5. Display the database" << endl;
    cout << "6. Exit from the program" << endl << endl;

    // get the user's choice
    cout << "Enter your option: ";
    cin >> UserInput;
    cout << endl;

    // act on the user's input
    switch(UserInput) {
      case '1':
            Enter(OpAmp[database_length], database_length);
         break;

      case '2':
            Save(OpAmp, database_length);
        break;

      case '3':
            Load(OpAmp, database_length);
        break;

      case '4':
            Sort(OpAmp, database_length);
        break;

      case '5':
            Display(OpAmp, database_length);
        break;

      case '6':
        return 0;

      default:
            cout << "Invalid Entry" << endl << endl;
        break;
    }
  }
}

void Enter(OpAmps& eOpAmp, unsigned long& database_length)
{
    cout<<"1) Enter Data"<<endl;

        if (database_length == DATABASE_MAX)
        {
            cout <<endl << "Database is full!!!" << endl;
        }
        else
        {
            cout << endl << "Name of OpAmp: ";
            cin >> eOpAmp.Name;
            cout << endl << "Number of Pins on OpAmp: ";
            cin >> eOpAmp.PinCount;
            cout << endl << "Slew Rate of OpAmp: ";
            cin >> eOpAmp.SlewRate;
            cout << endl<< "All Items Added!" << endl << "Now Save Your Data!" << endl;
            database_length++;
        }
}

void Save(OpAmps sOpAmp[], unsigned long database_length)
{
    cout<<"2) Save Data"<<endl;
    fstream output_file; 
    output_file.open(DATABASE_FILENAME, ios::out);

    if (!output_file.good())
        {
            cout << "Error Loading File!!!" << endl;
            return;
        }
    else
        {
            int i;
            output_file << database_length<< endl<<endl;
            for(i=0;i<=database_length-1;i++)
        {
            output_file << sOpAmp[i].Name << endl; 
            output_file << sOpAmp[i].PinCount<< endl;
            output_file << sOpAmp[i].SlewRate;
        }
            cout << endl << "Data Saved" <<endl;
        }
    output_file.close();
}

void Load(OpAmps lOpAmp[], unsigned long& database_length)
{
    cout<<"3) Load Data"<<endl; 
    fstream input_file;
    input_file.open(DATABASE_FILENAME, ios::in);
    if (!input_file.good())
        {
            cout << "Error Loading File!!!" << endl;
            return;
        }
    else
        {
            input_file >> database_length;
            for(int i=0;i<=database_length-1;i++)
                {
                    input_file >> lOpAmp[i].Name; 
                    input_file >> lOpAmp[i].PinCount;
                    input_file >> lOpAmp[i].SlewRate;
                }
        }
    input_file.close();
}

void Sort(OpAmps qOpAmp[], unsigned long database_length)
{
  cout<<"4) Sort Data"<<endl;
  char UserInput;
  // show the menu of options
    cout << endl;
    cout << "Sorting options" << endl;
    cout << "---------------" << endl;
    cout << "1. To sort by name" << endl;
    cout << "2. To sort by slew rate" << endl;
    cout << "3. No sorting" << endl << endl;
    // get the user's choice of sorting operation required
    cout << "Enter your option: ";
    cin >> UserInput;
    // act on the user's input
    switch (UserInput) {
        case '1':
            cout <<"Sort By Name"<<endl;
            QuickSortName (qOpAmp, database_length);
        break;
        case '2':
            cout <<"Sort By Slew Rate"<<endl;
            QuickSortSlewRate (qOpAmp, database_length);
        break;
        case '3':
            cout <<"No Sort"<<endl;
        break;
        default:
            cout <<"Invalid Entry"<< endl;
            return;
        break;
    }
}

void QuickSortName (OpAmps nOpAmp[], unsigned long database_length)
{
    OpAmps temp;    // Local variable used to swap records
    for(int i=0; i<database_length; i++)
    {
        for(int i=0; i<database_length; i++)
        {
            if(strcmp(nOpAmp[i].Name, nOpAmp[i+1].Name)>0)
            {
                temp = nOpAmp[i];
                nOpAmp[i] = nOpAmp[i+1];
                nOpAmp[i+1] = temp;
            }
        }
    }
    Display (nOpAmp, database_length);
}
void QuickSortSlewRate (OpAmps rOpAmp[], unsigned long database_length)
{
    OpAmps temp;    // Local variable used to swap records
    for(int i=0; i<database_length; i++)
    {
        for(int i=0; i<database_length; i++)
        {
            if(rOpAmp[i].SlewRate > rOpAmp[i+1].SlewRate)
            {
                temp = rOpAmp[i];
                rOpAmp[i] = rOpAmp[i+1];
                rOpAmp[i+1] = temp;
            }
        }
    }
    Display (rOpAmp, database_length);
}


void Display(OpAmps dOpAmp[], unsigned long database_length)
{
    cout<<"5) Display Data"<<endl;
    if (database_length == 0)
    {
        cout<<endl<< "Database is Empty!!!" <<endl;
    }
    else
    {   
        cout <<endl<<database_length<<" items are in the database" << endl;
        for (unsigned long i = 0; i <= (database_length-1); i++)
        {
            cout << endl << "Database Entry Number: " << i+1<< endl;
            cout << "Name: " << dOpAmp[i].Name <<endl;
            cout << "PinCount: " << dOpAmp[i].PinCount<<endl;
            cout << "Slew Rate: " << dOpAmp[i].SlewRate<< endl <<endl;

        }
    }
}

在输入每条数据后,选择保存,然后输入下一条,输入任意数量的项目后,加载数据,然后对数据进行排序。你会看到这个问题。任何帮助都可以解决这个错误!

【问题讨论】:

  • 你的排序代码在两个循环中都使用了i,所以我可以看到它在内部循环中超出了范围。我强烈建议您仔细检查一下快速排序算法。
  • 您的“快速排序”实际上是一种(次优)冒泡排序(其中存在严重错误)。也许考虑使用 C++ 中的内置排序工具(例如std::sort)?
  • 嗨,谢谢 Moo-Juice 的回答,我改变了这些,所以一个是 i,一个是 j,这并没有缓解问题。如前所述,按名称排序有效,但我看不出这与按转换速率排序之间的区别。谢谢!
  • 嗨卡梅伦,我没有意识到这是一个冒泡排序而不是快速排序,但无论哪种方式,我只需要它来做一个简单的排序。我现在不想更改太多代码,因为我对 C++ 还是很陌生。你能提供任何建议来优化我现在拥有的东西来消除这些错误吗?感谢您的宝贵时间!
  • 抱歉,已编辑我的评论以显示实际问题 - 您在排序期间超出了 OpAmps 数组的范围。

标签: c++ database qsort


【解决方案1】:
void QuickSortSlewRate (OpAmps rOpAmp[], unsigned long database_length)
{
    OpAmps temp;    // Local variable used to swap records
    for(int i=0; i<database_length; i++)
    {
        for(int i=0; i<database_length; i++)
        {

您的嵌套循环使用相同的变量 (i)。

if(rOpAmp[i].SlewRate > rOpAmp[i+1].SlewRate)

当 i 等于 (database_length - 1) 时,您将在此处离开数组的末尾。

void Save(OpAmps sOpAmp[], unsigned long database_length)
{
    ...
        for(i=0;i<=database_length-1;i++)
        {
            output_file << sOpAmp[i].Name << endl; 
            output_file << sOpAmp[i].PinCount<< endl;
            output_file << sOpAmp[i].SlewRate;         // **missing endl**
        }

而且您的文件格式可能已损坏 - 您的保存功能中缺少 endl

既然您使用的是 C++,为什么不使用 std::sort 而不是慢速冒泡排序?

// compare function for std::sort
bool CompareSlewRate(const OpAmps& a, const OpAmps& b)
{
    return a.SlewRate < b.SlewRate;
}

void QuickSortSlewRate (OpAmps rOpAmp[], unsigned long database_length)
{
    std::sort(rOpAmp, rOpAmp + database_length, CompareSlewRate);
    Display (rOpAmp, database_length);
}

【讨论】:

  • 感谢您的帮助啤酒男孩!我现在会用这个代码代替我的函数吗?然后仍然像我已经拥有的那样调用函数 QuickSortSlewRate 吗?我没有使用过 std: sort before 或 bool。我会试一试,看看它是如何处理代码的!如果我也更改我的 sortbyname 以进行排序但按字母顺序排列,会不会类似?谢谢!
  • 是的 - 您只需将 #include &lt;algorithm&gt; 添加到源文件的顶部。
  • 这并没有解决我最后一条数据损坏的问题
猜你喜欢
  • 2019-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-30
  • 2021-08-01
  • 1970-01-01
相关资源
最近更新 更多