2015-12-15 133 views
3

對於我的編程項目,我應該編寫一個程序來整理磁盤上的整數(即脫機排序)。我首先應該生成一些隨機整數,寫入所有這些整數,然後讀取其中兩個整數進行交換,然後將它們寫回到磁盤,然後重複這些步驟,直到數字排序。我能夠生成隨機數字就好了,打開文件沒有問題,但是當試圖寫入文件時崩潰。下面是我用來實現排序,包含排序算法的程序代碼的崩潰我的程序片段,而且代碼的片段:C++外部冒泡排序

void ReadAndWrite(int & rand_ints, int & pos_ints) 
{ 
    int rand_ints2 = 0; 

    GetNumber(pos_ints); 

    srand(time(0)); 

    fstream finout; 
    finout.open(SORTFILE, ios::binary | ios::in | ios::out); 
    if (finout.is_open()) 
    { 
     for (int i = 0; i < pos_ints; ++i) 
     { 
      rand_ints = rand() % 5; 
      finout.write(reinterpret_cast <char *>(rand_ints), sizeof(int) * 1); 
     } 

     for (int i = 0; i < pos_ints; ++i) 
     { 
      finout.seekg(ios::beg); 

      finout.read(reinterpret_cast <char *>(rand_ints), sizeof(int) * 2); 

      bubbleSort(&rand_ints, 2, sizeof(int), compare_ints); 

      finout.seekp(ios::app); 

      finout.write(reinterpret_cast <char *>(rand_ints), sizeof(int) * 2); 
     } 

     finout.close(); 
    } 
    else 
    { 
     cout << "File not opened!" << endl; 
    } 
} 

void GetNumber(int & pos_ints) 
{ 
    cout << "Enter a positive number: "; 
    cin >> pos_ints; 
} 

void bubbleSort(void * base, size_t num, size_t width, int(*compar) (const void *, const void *)) 
{ 
    bool done = false;//Allows us to enter loop first time 
    int hi = num - 1;//largest index is 1 less than the size of the array 
    while (!done) 
    { 
     done = true;//assume the list is sorted 
     for (int i = 0; i<hi; i++) 
     { 
      //pass thru the array up to 'hi' 
      //if (arr[i+1]<arr[i]) 
      if (compar((void *)(((char *)base) + width*(i + 1)), (void *)(((char *)base) + width*(i))) < 0) 
      { 
       //if any pair are out of order 
       done = false;//the list is not sorted 

          //int temp = arr[i];//swap them 
       void * tempp = (void *) new char[width]; 
       memcpy_s(tempp, width, (((char *)base) + width*(i)), width); 

       //arr[i] = arr[i+1]; 
       memcpy_s((((char *)base) + width*(i)), width, ((char *)base) + width*(i + 1), width); 

       //arr[i+1]=temp; 
       memcpy_s(((char *)base) + width*(i + 1), width, tempp, width); 


       delete[] tempp; 
      } 
     } 
     hi--;//at the end of a pass, largest item in that pass is in proper place; no need to go this far next time 
    } 
} 

int compare_ints(const void * arg1, const void * arg2) 
{ 
    int return_value = 0; 

    if (*(int *)arg1 < *(int *)arg2) 
     return_value = -1; 

    else if (*(int *)arg1 > *(int *)arg2) 
     return_value = 1; 

    return return_value; 
} 

它崩潰的代碼finout線.write(reinterpret_cast(rand_ints),sizeof(int)* 1);在第一個for循環(第52行)中,出現以下錯誤:ExternalSort.exe中的0x55916D16(msvcp140d.dll)引發異常:0xC0000005:訪問衝突讀取位置0x00000001。 有沒有辦法解決這個錯誤,並使這個排序程序的工作?試過我可能試過的一切,並且我看不到一行代碼導致程序崩潰或導致其他問題。

回答

1

由於rand_intsint類型,因此您可能的意思是reinterpret_cast<char *>(&rand_ints)(注意&)。否則,你會使指針脫離整數值。

OTOH,試圖將兩個相鄰的整數讀入單個整數變量的地址很可能會導致問題。

更深入地研究你的排序算法,在我看來你試圖將它推廣到任何大小的數據元素,而不僅僅是ints。但是,它仍然清晰地面向陣列;如果您想處理文件,則可能必須傳遞該函數的文件名或fstream參考。另外,除非你被要求使用Bubble Sort,否則我會強烈建議你不要這樣做,尤其是對於磁盤上的排序,除非你確定你的數據集非常非常小(比如說,不超過一百個數字)。對於就地排序,我建議你使用快速排序。

+0

實際上,根據我對Knuth的排序和搜索的回憶,我認爲冒泡排序可以適用於排序未存儲在內存中的大型數據集。 (當然,他是在談論9磁道磁帶而不是磁盤,但氣泡排序的好處在於它可以順序訪問所有東西。 –

+0

我還懷疑海報被指示使用氣泡排序作爲課程的一部分。我懷疑對整數1TB數據庫進行排序的最佳方式是:將0.5 GB的塊讀入內存,使用quick_sort進行排序並寫出,然後對生成的200個流進行合併排序。 –