Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

vector class 2

Status
Not open for further replies.

tmcneil

Technical User
Nov 17, 2000
294
US
I have some code where I have used an array to store integer data from a file, sort and print it. I would like to replace the array with the vector class, but it's not as easy as I had hoped. I have a class that I replaced the array with the vector, vector<int> nums;. I have a method where I am opening the data file and reading integers into the vector. I get a compile error:
Code:
error C2228: left of '.push_back' must have class/struct/union type

This is the method:
Code:
void VectorArray::read_scores (void)
{
    int temp_num;
    nums.resize(n);

    infile >> temp_num;  // read score in temporary location; prime read   

    while (!infile.eof() && count < 50)   //read no more than 100 numbers
    {
        if (count = 20)
            nums.resize(35);    //resize nums vector class from 20 to 35.

        nums.at(count).push_back = temp_num;
        //scores_ary[count] = temp_num;        //store number read in array
        count++;
        // read next number in temporary location
        infile >> temp_num;  //next read just before end of while loop
    }
}//end read_scores

So, what would be the fix?.

Thanks in advance,
Todd
 
push_back is a function. Use:
Code:
nums.push_back( temp_num );
Also, why are you resizing the vector all the time? The whole point of a vector is that it resizes itself when it needs to.
 
I'm trying to use a class to initialize the vector to 20 items, then if 20 items is reached, resize to 35. My data file has no more than 35 integers in it. Here's my class:

Code:
#ifndef VECTORARRAY
#define VECTORARRAY
#define MAX 50
class VectorArray
{
	 private:
         ifstream infile;             //input file declaration
         vector<int> nums;            // vector class, nums
         int scores_ary [MAX];        //an array to store 1 field of numbers
		 int count;                   //number of records stored in array
         //int largest, smallest;     //largest and smallest number
         int n, pg;                      //used for numbering pages

	 public:
		 VectorArray(void);              //constructor
		 ~VectorArray (void);            //destructor
		 void read_scores (void);        //Reads data from the file and stores into array
         void print_scores (char ch);    //Print original and sorted data items
         //void lasm_ary (void);        //computes largest and smallest numbers in array
         void sort_scores (void);        //sorts array in ascending order
         //void comp_frequency (void);  //determines frequency of all data items
         void comp_mean (void);       //computes mean (average) of all data items

}; //end class VectorArray
#endif

So, I tried the nums.push_back( temp_num ); and when I place a breakpoint at that line, the program generates an error in the vector file that comes with c++.
Code:
void _Xran() const
		{	// report an out_of_range error
		_THROW(out_of_range, "invalid vector<T> subscript");
		}

does this mean I'm not supposed to use a class? is there a way to intialize the vector with a 20 items in the class definition?
 
Post your new code and indicate where the exception is thrown.

BTW, member variables of a class usually begin with m_ to make them stand out from function level variables (i.e. m_infile, m_nums, m_count...)
 
Well, I'm not getting the exception error anymore, just erroneous results, like the number 32 getting printed out 50 times to the acreen. Weird. Here's my class:
Code:
#include <fstream>
#include <iostream>
#include <vector>
#include <ctype.h>

using namespace std;

//Declare an array of class VectorArray

#ifndef VECTORARRAY
#define VECTORARRAY
#define MAX 50
class VectorArray
{
	 private:
         //preceding class member variables with: m_
         ifstream m_infile;             //input file declaration
         vector<int> nums;            // vector class, nums
         //int scores_ary [MAX];        //an array to store 1 field of numbers
		 int m_count;                   //number of records stored in array
         //int largest, smallest;     //largest and smallest number
         int m_n, m_pg;                      //used for numbering pages

	 public:
		 VectorArray(void);              //constructor
		 ~VectorArray (void);            //destructor
		 void read_scores (void);        //Reads data from the file and stores into array
         void print_scores (char ch);    //Print original and sorted data items
         //void lasm_ary (void);        //computes largest and smallest numbers in array
         void sort_scores (void);        //sorts array in ascending order
         //void comp_frequency (void);  //determines frequency of all data items
         void comp_mean (void);       //computes mean (average) of all data items

}; //end class VectorArray
#endif

Here's my constructor where I open the data file with 50 integers
Code:
VectorArray::VectorArray (void)
{
    m_count = 0;
    m_n = 50;
    m_pg++;

    nums.resize(m_n);  //resize nums vector to 50
    m_infile.open ("Lab6Data.txt");

    if (m_infile.fail()) //see if file opened successfully
    {
        cout << "File, Lab6Data.txt, could not be opened!\n\n";
	    system ("pause");   //so the message can be read
	    exit (1);  // abort the program
	}

    //clear the vector
    for(int i = 0; i < m_n; i++)
	        nums.at(i)= ' ';

}// end constructor

Method to read integers into vector:
Code:
void VectorArray::read_scores (void)
{
    int temp_num;

    m_infile >> temp_num;  // read score in temporary location; prime read

    //for (int i = 1; i <= n; i++)
    //    nums.push_back(i);

    while (!m_infile.eof() && m_count < m_n)   //read no more than 50 numbers
    {
        nums.push_back( temp_num );
        m_count++;
        // read next number in temporary location
        m_infile >> temp_num;  //next read just before end of while loop
    }
}//end read_scores

method to print integers:
Code:
void VectorArray::print_scores (char ch)
{
    switch (ch)
	{
	   case 'o':  cout << "\n\t\t      Original List of Data Items Read\n\n";
                  cout << "\t\t\t\t" << SEPARATOR << endl;
                  break;
       case 's':  m_pg++;
                  cout << "\n\n\t\t\t\t\t\t\t\t  Page No. " << m_pg << endl;
                  cout << "\n\n\t\t       Sorted List of Data Items Read\n\n";
                  cout << "\t\t\t        By: " << NAME;
                  cout << endl << endl << "\t\t\t        " << SEPARATOR << endl;
                  break;
	} //end switch

    for (int i = 0; i < m_count; i++)
    {
        if (i % 15 == 0)
            cout << endl;
        
        cout << setw(5) << right << nums.at(i);
    }

    cout << endl << DASHES << endl;
    cout << "\t\tTotal Number of Data Items Processed = " << m_count <<  "."
         << endl << endl;
}  // end print_scores()

My output of the original vector looks like this, which is obviously out of whack.:
Code:
                      Original List of Data Items Read

                                ---------------

   32   32   32   32   32   32   32   32   32   32   32   32   32   32   32
   32   32   32   32   32   32   32   32   32   32   32   32   32   32   32
   32   32   32   32   32   32   32   32   32   32   32   32   32   32   32
   32   32   32   32   32
---------------------------------------------------------------------------
                Total Number of Data Items Processed = 50.

Not sure what I am doing wrong, but the code is able to compile. Seems like the values aren't getting stored correctly into the vector.

Todd
 
Code:
nums.at(i)= ' ';
nums is a vector of ints, but here you are assigning a space to it. I'm surprised the compiler didn't complain about that. 32 is the ASCII value of a space (if I'm not mistaken).

You need to stop using the vector.resize() function all together. There are very few cases when you actually need to use resize(), and this isn't one of them.

What's happening is, you resize the vector to 50 elements. Then you add your 50 ints with the push_back() function, but since the vector is already 50 ints big, it adds them in elements 51-100.

A vector is basically an array that automatically grows each time you call push_back(), which adds a new element to the end of the vector and assigns the value you pass to it. push_front() on the other hand, will add a new element to the end of the vector, then move every element back one (to free up space at the beginning), then assign the value you pass to the first element.

Also, vector has an operator[] defined, so these two lines do exactly the same thing:
Code:
i = nums.at( 5 );
i = nums[ 5 ];
I prefer using the [] style since it's shorter and looks cleaner.

OK, so to sum things up, remove all code that uses resize(), and basically remove everything from your constructor except the file opening code which you can change to:
Code:
VectorArray::VectorArray()
:   m_infile( "Lab6Data.txt" ),  // This is an initializer list.
    m_count( 0 ),                // It's more efficient.
    m_n( 50 ),
    m_pg( 0 )

{
   if ( !m_infile ) //see if file opened successfully
   {
        cout << "File, Lab6Data.txt, could not be opened!\n\n";
        system( "pause" );   //so the message can be read
        exit( 1 );  // abort the program
   }
}
 
Got rid of the resize() and use the push_back. The code works great now and it's also cleaned up a bit. I'm getting the output that I expected to see. Also, if I have to delete a value of a known index from a vector, that's not hard right. Well, I'm in the middle of another assignment that uses functions and parameters by reference to pass the vector values. I have this as my prototype and call:
Code:
void deleteArray(const vector <int>& b, int deleteIndex, int &index);

vector <int> a;
int deleteIndex = 5;          // index of element to delete
int index = 10;

    cout << "After deletion of " << a.at(deleteIndex) << ":" << endl;
    // Exercise 4	- Call deleteArray to delete a.at(deleteIndex)
    deleteArray(a, deleteIndex, index);

void deleteArray(const vector <int>& b, int deleteIndex, int &index)
{
    b.erase(deleteIndex);
    index = b.size();

    //cout << "Stub for deleteArray" << endl;
}

I'm trying to use the erase() function, but I get a compile error:
Code:
error C2663: 'std::vector<_Ty>::erase' : 2 overloads have no legal conversion for 'this' pointer

I'm looking at some examples on the web and it looks like this is how it's done.

Todd
 
To erase an element at a specific index, use:
Code:
b.erase(b.begin() + deleteIndex);
That is required because erase takes an iterator, and if you add the index to an iterator pointing at the first element it will take you to the element you want to erase.

cpjust said:
Also, vector has an operator[] defined, so these two lines do exactly the same thing:
Code:
i = nums.at( 5 );
i = nums[ 5 ];
I prefer using the [] style since it's shorter and looks cleaner.
They aren't exactly the same. The square brackets don't do range-checking, so if you pass an out of bounds index you will get undefined behavior. If you pass an out of bounds index to at() you will get an exception which tells you exactly what went wrong. The additional range check provided by at() might cause minor performance issues, but in most apps it shouldn't be a problem.
 
I forgot to add that you cannot erase from a const vector, so the parameter for the second function should be a non-const reference.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top