Just a pathetic student that's stuck

Discussion in 'C++' started by yourfriendred, Mar 13, 2011.

  1. yourfriendred

    yourfriendred New Member

    Joined:
    Mar 13, 2011
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    Occupation:
    Student
    Location:
    Southfield, Michigan
    I've never been posted or even lurked in a forum before so please be patient. I'm writing this program for class and I'm stuck. If someone could give me some advice I'd appreciate it. The program asks the user to input to array of numbers that are than compared. It then reports back where they intersect and where they union. The part I'm stuck on right now is a function that's supposed to when called create an empty set. Also the unionOfSets I'm not sure if I have correct either.

    Code:
    / Lab 2: IntegerSet.cpp
    // Member-function definitions for class IntegerSet.
    #include <iostream> 
    using std::cout; 
    using std::cin; 
    using std::cerr;
    
    #include <iomanip> 
    using std::setw; 
    
    /* Write include directive for IntegerSet.h here */
    #include "IntegerSet.h"
    
    // constructor creates a set from array of integers
    IntegerSet::IntegerSet( int array[], int size)
    {
       emptySet();
    
       for ( int i = 0; i < size; i++ )
          insertElement( array [ i ] );
    } // end IntegerSet constructor
    
    /* Write a definition for emptySet */
    void IntegerSet:: emptySet()
    {
    	int array[]={0};
    }
    
    
    
    // input a set from the user
    void IntegerSet::inputSet()
    {
       int number;
    
       do 
       {
          cout << "Enter an element (-1 to end): ";
          cin >> number;
    
          if ( validEntry( number ) )
             set[ number ] = 1;
          else if ( number != -1 )
             cerr << "Invalid Element\n";
       } while ( number != -1 ); // end do...while
    
       cout << "Entry complete\n";
    } // end function inputSet
    
    // prints the set to the output stream
    void IntegerSet::printSet() const
    {
       int x = 1;
       bool empty = true; // assume set is empty
       
       cout << '{';
    
       for (int u = 0; u < 101; u++ )
       {
          if ( set[ u ] ) 
          {
             cout << setw( 4 ) << u << ( x % 10 == 0 ? "\n" : "" );
             empty = false; // set is not empty
             x++;
          } // end if
       } // end for
    
       if ( empty )
          cout << setw( 4 ) << "---"; // display an empty set
    		
       cout << setw( 4 ) << "}" << '\n';
    } // end function printSet
    
    // returns the union of two sets
    IntegerSet IntegerSet::unionOfSets( const IntegerSet &r )
    {
       IntegerSet temp;
    
       // if element is in either set, add to temporary set
       for ( int n = 0; n < 101; n++ )
          if ( set[ n ] == 1 || r.set[ n ] == 1 )
             temp.set[ n ] = 1;
    
       return temp;
    } // end function unionOfSets
    
    /* Write definition for intersectionOfSets */
    
    IntegerSet IntegerSet::intersectionOfSets(const IntegerSet &r)
    {
    	IntegerSet temp;
    
      for ( int n = 0; n < 101; n++ )
          if ( set[ n ] == 1 && r.set[ n ] == 1 )
             temp.set[ n ] = 1;
    
       return temp;
    }
    // insert a new integer into this set
    void IntegerSet::insertElement( int k)
    {
       if ( validEntry( k) )
          set[ k ] = 1;
       else
          cerr << "Invalid insert attempted!\n";
    } // end function insertElement
    
    /* Write definition for deleteElement */
    void IntegerSet :: deleteElement(int k)
    {
    	set[k] = 0;
    }
    /* Write definition for isEqualTo */
    bool isEqualTo(const IntegerSet &r);
    
    // determines if two sets are equal
    bool IntegerSet::isEqualTo(const IntegerSet &r) const
    {
       for ( int v = 0; v < 101; v++ )
          if ( set[ v ] != r.set[ v ] )
             return false; // sets are not-equal
    
       return true; // sets are equal
    } // end function isEqualTo
     
    Last edited by a moderator: Mar 14, 2011
  2. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    Lurking on a forum is a good idea cos you get to see how it works and to observe the posting etiquette.

    When new to a forum ALWAYS ALWAYS read the FAQ. This means "Frequently Asked Questions" and covers loads of useful stuff that is often asked by newbies. Also make sure you read the posting guidelines, which are linked from where you create a new post on Go4Expert, so you can understand how to approach the community. For example it tells you about code blocks, which maintain the formatting of posted code. Your omission of code blocks shows you haven't read them, so go and read them now.

    A common newbie programming error is to try to write thousands of lines of code before compiling it. Don't do that. Write a small amount, compile it, fix the errors (and with such a small amount of code there will either be no errors or very limited scope for those errors), then write a bit more. You have an error right there on line 1 (although TBF this could be a copy/paste error):
    Code:
    / Lab 2: IntegerSet.cpp
    
    Comments are either // for the line or /* */ for containing a block of text. / on its own is a division operator, so this line will throw an error.

    >> The part I'm stuck on right now is a function that's supposed to when called create an empty set.

    OK, let's see what you've got so far:
    Code:
    /* Write a definition for emptySet */
    void IntegerSet:: emptySet()
    {
    	int array[]={0};
    }
    
    If you're supposed to do this in a function then you should have learnt by now about stack and heap storage. Basically, stack storage is temporary storage for functions, which is deleted when that function returns. So you can't create anything new in a function, unless it's only going to be used directly in that function. If you still want the resource to exist when the function returns, then you must create it on the HEAP instead of the stack. To do this, use malloc ***AND FREE***, i.e. don't forget to clean up after you're done. Memory leaks, where you keep on creating new stuff without deleting it after you're done with it, are major problems in software so let's deal with this at the earliest possible time. Whenever you write malloc, write free, at least in such a way as to cause a syntax error so you force yourself to deal with it before you forget about it. Or add an entry to a TODO list, or something.

    Your attempt to create a literally empty set suggests you have a maths background. Computers don't work like that. Empty sets really aren't much use, if you want to create one, don't bother. Computers use array storage, which is a fixed size, or you could get complicated and start using C++ vectors but I suspect this is currently way beyond you.

    So first you need to decide how many ints you want in the array. Ah, of 125 lines, you have no "main" function. This is the starting point for the program, so you will need a main function, and I suggest you write this first.

    OK, here's a function that could be considerably simpler:
    Code:
    IntegerSet::IntegerSet( int array[], int size)
    {
       emptySet();
    
       for ( int i = 0; i < size; i++ )
          insertElement( array [ i ] );
    } // end IntegerSet constructor
    
    Don't try to do it this way, it'll really suck. Since you know the size when this function starts, you can just create the array directly.
    Code:
    IntegerSet::IntegerSet( int **array, int size)
    
    I've changed the definition of array to a pointer to a pointer to int. The calling function will have defined something like
    Code:
    int *myArray;
    
    It doesn't know the size so it can't allocate storage. To modify a value in a function, you have to pass the address of that value, and this is also true of pointers, so it will call the function with something like:
    Code:
    IntegerSet(&myArray,size);
    
    So continuing with the function definition:
    Code:
    IntegerSet::IntegerSet( int **array, int size)
    {
        int *oneWay=malloc(size*sizeof(int));
        //...
        *array=oneWay;
        return;
        
        // another way:
        *array=malloc(size*sizeof(int));
        //...
        return;
    }
    
    You can do it two ways here. You can create a new array and have the pointer returned to a local variable of yours (oneWay), do what you need to do with automatic semantics, then assign the pointer to *myarray when you're done, or you can work directly with *myarray. The former may be simpler for you at this stage, but the latter is preferable as it doesn't require that extra bit of storage.

    /me looks for insertElement(), finds it, then validEntry(). You haven't written this yet. Here's a hint that ties in with what I said earlier: don't call functions you haven't written yet. Top down design isn't that clever, it forces you to create stubs before you can test any code, so a better route is to use bottom up design, where you write the lowest level first then write calling functions on top of that.

    Anyway, as I said, this approach sucks, and your insertElement( int k) won't work anyway. Extending an array is not as simple as just doing
    Code:
    set[ k ] = 1;
    
    - this also suggests you have a strong mathematical background; this is perfectly OK in maths, but definitely inappropriate to array manipulation within C++. An array cannot be extended, so you would have to malloc a new array with the new size, copy all the elements over, free() the old array and add your new element. Do not even attempt to do this.

    This also suggests you have the concept of arrays the wrong way round. If you really want set[k]=1, and k=1000, then your array will have to be at least 1001 elements long. But if you want the array to contain, say, {3,1000,27}, then that only needs to be 3 elements long. set[0]=3, set[1]=1000, set[2]=27 (don't forget C starts counting from zero).

    You might want to zero-initialise your new array, so here's my suggestion for the complete function:
    Code:
    IntegerSet::IntegerSet( int **array, int size)
    {
        int *oneWay=malloc(size*sizeof(int));
        for (int i=0; i<size; i++)
            oneWay[i]=0;
    
        *array=oneWay;
        return;
    }
    
    IntegerSet::~IntegerSet()
    {
        // hmm.  For correct balancing, anything created in the constructor
        // should be destroyed in the destructor, but destructors take no
        // arguments, so myArray will have to have been destroyed before you
        // get to this point.
    }
    
    
    Where does the number 101 come from in IntegerSet::unionOfSets()?

    Going back to an early suggestion: start simple. You've got waaaaaaay too much code at the moment. Create a main function and no other code yet. Just start with a hello world program. When that works, just add enough to the IntegerSet class to create a new array and display it. Don't attempt to do any more than that yet. Compile, debug and run it, make sure it works. Then you can start adding more bits, and make sure you test before moving on.

    Also a comment that will blow a lot of the above out of the water: the array probably needs to be a member attribute of the IntegerSet class. So there won't be any need to pass an array into the constructor, unless you want to implement a copy constructor, but you don't need to do that yet and certainly shouldn't start with it. Also you'll be able to destroy it in the destructor.
     
    Last edited: Mar 14, 2011
    shabbir likes this.

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice