2015-10-17 80 views
1

對於這個程序,我想創建一個SET類,其中包含一組正數和不重複的數學集合。在創建SET類之後,我創建了重載運算符,用於+和*以將兩個集合添加到一起,並分別找到兩個集合的相交編號。然而,在我開始測試代碼之後,我發現+和*重載操作符不能在包含數字的兩組數據上工作,除非我創建了一個新的SET來輸出數據。例如,我不得不這樣做:帶類的C++重載操作符

SET set3 = set1 + set2; 
cout << set3; 

不是能夠只是做:

cout << set1 + set2; 

我能夠輸出上面的代碼只有兩套是空的,或者1套裝滿並另一個是空的。我不確定我做錯了什麼,因此無法輸出兩個填充集。我把我的代碼分成了三個文件。 這裏是頭文件:

//CSCI 205 
//Brett Milinski 
//Assignment 2 - The Set Class 
//This problem wants us to create a set class to hold a mathematical set of integers and can later be manipulated to implement the Sieve of Eratosthenes method for computing prime numbers 

    #ifndef SET_H 
    #define SET_H 
    #include<iostream> 
    using namespace std; 

    class SET 
    { 
    private: int a[50]; 
      int length; 
      const int SIZE = 50; 

    public: SET(); 
      SET(int a, int b); 
      void print(ostream &os); 
      void insert(int x); 
      void erase(int x); 
      int searchList(int a[], int length, int x); 
      int addSearchList(int a[], int length, int x); 
      friend SET& operator+(SET& a, SET& b); 
      friend SET& operator*(SET& a, SET& b); 
      friend ostream& operator<<(ostream& os, SET& a); 
      SET& sieveOfEratosthenes(int n); 
    }; 
    #endif 

這裏是set.cpp文件定義的方法:

//CSCI 205 
//Brett Milinski 
//Assignment 2 - The Set Class 
//This problem wants us to create a set class to hold a mathematical set of integers and can later be manipulated to implement the Sieve of Eratosthenes method for computing prime numbers 

#include"set.h" 
#include<iostream> 
using namespace std; 

SET::SET() //default constructor 
{ 
    length = 0; 
} 

SET::SET(int start, int end) //overloaded constructor 
{ 
    length = end - start + 1; //end of range of numbers to be input 

    if (length <= SIZE) //range isn't too big for the array 
    { 
     for (int x = 0; x < length; x++) 
     { 
      a[x] = start; 
      start++; 
     } 
    } 
} 

void SET::insert(int x) //function to insert numbers from the array 
{ 
    bool inserted = false; 

    for (int i = 0; i < length; i++) //check to see if the value is already in the set, if so, don't add 
    { 
     if (a[i] == x) 
     { 
      inserted = true; 
      cout << "Sorry, the SET already contains that number." << endl; 
     } 
    } 

    if (inserted == false) //the SET does not contain the number that is trying to be inserted 
    { 
     int check = addSearchList(a, length, x); //check the position of where to add the value 

     if (length == SIZE) //check to see if the array is already full 
     { 
      cout << "You cannot add anymore elements to this array because it is full." << endl; 
     } 
     else if (check == length) //check to see if it is added at the end 
     { 
      length++; //make the array one size bigger to make room for the addition 
      a[length - 1] = x; //add the value to the end 
     } 
     else 
     { 
      length++; //make the array one size bigger to make room for the addition 
      for (int i = length - 1; i >= check; i--) //start at the bottom and move up towards where the new value should be 
      { 
       a[i] = a[i - 1]; //ripple down 
      } 
      a[check] = x; //add in the new value 
     } 
    } 

} 

void SET::erase(int x) //function to erase numbers from the array 
{ 
    int check = searchList(a, length, x); //check to see what the position is 

    if (length == 0) //check to see if the array is empty before deleting anything 
    { 
     cout << "The array is empty and therefore nothing can be deleted from the elements." << endl; 
    } 
    else if (check != -1) //check to see if the value is found 
    { 
     for (int x = check; x < length - 1; x++) 
     { 
      a[x] = a[x + 1]; //ripples every element up 
     } 
     length--; //makes the array one size smaller to accomadate the deletion 
    } 
    else 
    { 
     cout << "The value entered is not in the array." << endl; //the value being checked for does not exist 
    } 

} 

void SET::print(ostream &os) //function to output the values of the array 
{ 
    os << "The contents of the set are:" << endl; 
    for (int x = 0; x < length; x++) 
    { 
     os << a[x] << " "; 
    } 
    os << endl; 
} 

int SET::searchList(int a[], int length, int x) //a search for the erase function 
{ 
    int index = 0;    // Used as a subscript to search array 
    int position = -1;   // Used to record position of search value 
    bool found = false;   // Flag to indicate if the value was found 

    while (index < length && a[index] <= x && !found) 
    { 
     if (a[index] == x) // If the value is found 
     { 
      found = true;   // Set the flag 
      position = index;  // Record the value's subscript 
     } 
     index++;     // Go to the next element 
    } 
    return position;    // Return the position, or -1 
} 

int SET::addSearchList(int a[], int length, int x) //a search for the insert function 
{ 
    int index = 0;    // Used as a subscript to search array 
    int position = -1;   // Used to record position of search value 

    while (index < length && a[index] <= x) 
    { 
     index++;     // Go to the next element 
    } 
    if (index == length) //all the values were smaller than the number trying to be added 
    { 
     position = length; //position is at the end of the array 
    } 
    else 
    { 
     position = index; //found where to add the new element 
    } 
    return position;    // Return the position, or currentSize 
} 

//calls the print function to print to the output stream 
ostream& operator<<(ostream& os, SET& a) 
{ 
    a.print(os); 
    return os; 
} 

//join the two sets together 
SET& operator+(SET& a, SET& b) 
{ 
    SET added;//empty set to add to 

    if (a.length == 0 && b.length != 0) //for empty sets 
    { 
     return b; 
    } 
    else if (b.length == 0 && a.length != 0) //for empty sets 
    { 
     return a; 
    } 
    else 
    { 
     for (int x = 0; x < a.length; x++) //add in the elements from the first set 
     { 
      added.insert(a.a[x]); 
      cout << added.a[x] << endl; 
     } 

     for (int x = 0; x < b.length; x++) //add in the elements from the second set 
     { 
      added.insert(b.a[x]); 
      cout << b.a[x] << endl; 
     } 

     return added; //returns the added set 
    } 
} 

//find what the two sets have in common 
SET& operator*(SET& a, SET& b) 
{ 
    int shortestLength = 0; 
    SET inCommon; 

    if (a.length < b.length) //find the shortest length 
    { 
     shortestLength = a.length; 
    } 
    else 
    { 
     shortestLength = b.length; 
    } 

    //search through and find the highest common number between the sets 
     for (int x = 0; x < shortestLength; x++) 
     { 
      for (int i = 0; i < shortestLength; i++) 
      { 
       if (a.a[i] == b.a[x]) //see if it shares it and has it in common 
       { 
        inCommon.insert(a.a[i]); //put in the shared value 
       } 
      } 
     } 

     return inCommon; //return the common numbers 
} 

這裏是先前定義的,用於測試的不同方法的setTest.cpp:

//CSCI 205 
//Brett Milinski 
//Assignment 2 - The Set Class 
//This problem wants us to create a set class to hold a mathematical set of integers and can later be manipulated to implement the Sieve of Eratosthenes method for computing prime numbers 

#include"set.h" 
#include<iostream> 
using namespace std; 

int main() 
{ 
    int dummy = 0; 
    SET set1(1, 7); //overloaded constructor 
    SET set2, set4; //default constructor 
    SET set3(5, 10); 
    SET set7(9, 11); 

    //testing the functions of the SET class (overloaded constructor) 
    cout << set1; 
    cout << "Insert 5:" << endl; 
    set1.insert(5); //try inserting to end 
    cout << set1; 
    cout << "Try insertering 5 again:" << endl; 
    set1.insert(5); //try inserting a duplicate number 
    cout << set1; 
    cout << "Insert 0:" << endl; 
    set1.insert(0); //try inserting to start 
    cout << set1; 
    cout << "Erase 3:" << endl; 
    set1.erase(3); //try erasing from middle 
    cout << set1; 
    cout << "Insert 3:" << endl; 
    set1.insert(3); //try inserting to the middle 
    cout << set1; 
    cout << "Erase 0:" << endl; 
    set1.erase(0); //try erasing from the start 
    cout << set1; 
    cout << "Erase 5:" << endl; 
    set1.erase(5); //try erasing from the end 
    cout << set1; 
    cout << "Erase 20 (shouldn't work because it isn't there):" << endl; 
    set1.erase(20); //try erasing something that isn't there 
    cout << set1; 
    cout << "Add to the empty set (set2) and then erase from it:" << endl; 
    set2.insert(1); //try adding to the empty set 
    cout << set2; 
    set2.erase(1); //try erasing from the now populated set 
    cout << set2; 

    //test second set (default constructor) 
    cout << "This is the default constructor (an empty set, should contain no values)." << endl; 
    cout << set2; 

    //try adding two overlapping sets together 
    cout << "Try adding two overlapping sets together:" << endl; 
    cout << "The First Set:" << endl; 
    cout << set1; 
    cout << "The Other Set:" << endl; 
    cout << set3; 
    cout << "After adding the sets together together:" << endl; 
    SET set5 = set1 + set3; 
    cout << set5; 

    //try adding two empty sets 
    cout << "Try adding two empty sets together:" << endl; 
    cout << "The First Set:" << endl; 
    cout << set2; 
    cout << "The Other Set:" << endl; 
    cout << set4; 
    cout << "After adding the sets together together:" << endl; 
    cout << set2 + set4; 

    //try adding one filled set and one empty set 
    cout << "Try adding one filled set and one empty set together:" << endl; 
    cout << "The First Set:" << endl; 
    cout << set1; 
    cout << "The Other Set:" << endl; 
    cout << set2; 
    cout << "After adding the sets together together:" << endl; 
    cout << set1 + set2; 

    //try adding two sets that don't overlap 
    cout << "Try adding two sets that don't overlap:" << endl; 
    cout << "The First Set:" << endl; 
    cout << set1; 
    cout << "The Other Set:" << endl; 
    cout << set7; 
    cout << "After adding the sets together together:" << endl; 
    cout << set1 + set7; 

    //find out what the sets have in common 
    cout << "Find what the two sets have in common:" << endl; 
    cout << "The First Set:" << endl; 
    cout << set1; 
    cout << "The Other Set:" << endl; 
    cout << set3; 
    SET set6 = set1 * set3; 
    cout << "The number that the two sets have in common is contained in the set below (if 0, there is no common number unless it is 0)" << endl; 
    cout << set6; 


    cout << "Enter a dummy number:" << endl; 
    cin >> dummy; 
    return 0; 
} 

我不知道爲什麼我不能做我想做的事,在此先感謝對我的問題的任何幫助!

+0

什麼是錯誤信息? – Downvoter

+3

這是很多代碼。你能簡化它到一個最小的例子,演示你遇到的問題嗎? – user3553031

回答

2

兩個功能

SET& operator+(SET& a, SET& b); 
SET& operator*(SET& a, SET& b); 

返回一個參照本發明的臨時對象:

SET& operator+(SET& a, SET& b) 
{ 
    SET added; 

    // ... 

    return added; // <= temporary object returned via a reference - don't!! 
} 

這些臨時對象(addedinCommon)由編譯器通常被分配在堆棧上和「消失」當控制流離開它們被定義的函數時,你最終得到懸掛引用。這是一個非常討厭的錯誤。

要解決此問題,請確保按值而不是按引用返回這些對象。所有需要的是改變返回類型,像這樣:

SET operator+(SET& a, SET& b); 
SET operator*(SET& a, SET& b); 
^^^ 
no more references here 
+0

感謝您的意見。我給出的作業單據稱將它們作爲參考,但我可以看到你所說的是做到這一點的正確方法。我一定會和老師談談這件事,再次感謝! – user2922247

1
從問題 mentioned by @WhiteViking

除此之外,您的

friend ostream& operator<<(ostream& os, SET& a); 

聲明應該是

friend ostream& operator<<(ostream& os, const SET& a); 

否則你不會能夠將rvalues(即臨時對象)綁定到參數a。在代碼中,在行std::cout << set1 + set2;中,operator<<的第二個參數是右值set1 + set2,它只能綁定到右值引用或const引用。一旦實施這些更改,您將可以使用std::cout << set1 + set2;,而不會有任何問題。