vijayan121 1,152 Posting Virtuoso

the label menu: (line 28) hides the variable char menu (line 12). you could use the scope
resolution operator (::menu) to make the error go away; but hiding names like this is not a good idea.
technically, a label is a pointer (address).

vijayan121 1,152 Posting Virtuoso

Gah!!! No matter what I do, every time I make a correct implementation of this priority queue, when I try to run my program, I get this:
---------------------------
Microsoft Visual C++ Debug Library
---------------------------
Debug Assertion Failed!
Program: ...
File: c:\program files\microsoft visual studio 8\vc\include\algorithm
Line: 2025
Expression: invalid operator<
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
---------------------------
Abort Retry Ignore
---------------------------

No matter what little tricks I try!

My current predicate looks like this:

struct comp
{
bool operator() ( const Node* first, const Node* second ) const
{
if (first->getHeuristic() > second->getHeuristic()) {
return true;
}
else if (second->getOrder() < first->getOrder()) {
return true;
}
else {
return false;
};
}
};

the only way this thing will run is if I make the < in the first else if statement a >, which orders them backwards. What the heck is going on???

i had said in my earlier reply

remember that the predicate must be a relation that is asymetric,
irreflexive and transitive; ie. one that imposes a strict oredering
on the sequence.

because it is important to understand it.

take two nodes
node_a ( getHeuristic returns 10, getOrder returns 6) and
node_b ( getHeuristic returns 11, getOrder returns 5)

comp()(a,b) returns true
if (first->getHeuristic() > second->getHeuristic()) // false

vijayan121 1,152 Posting Virtuoso

However, if I use the correct predicate: ...

the predicate you have written (as the correct one) is equivalent to

bool operator() ( const Node* first, const Node* second ) const
{
  return first->getHeuristic() > second->getHeuristic() ;
  // in all other cases you are returning false
}

the order is not involved at all.

vijayan121 1,152 Posting Virtuoso

Actually, I have one more quick question. I'd actually like this to be a priority_queue of Node* (pointers to Node), but if I do that, then it sorts the queue using pointer arithmetic. So the Node*s with the lower addresses are put at the front and the higher ones are at the back. Is there any way for me to define a custom way to sort them in the Node class? Like, can I overload the "<" operator for just Node pointers somehow? Know what I mean?

pointers are a standard type and you can not define how pointers are to be
compared anywhere. however, you can tell the priority_queue of Node*
how you want priorities to be compared.
a. write a binary predicate to compare nodes

struct compare_node_pointers
{
  bool operator() ( const Node* first, const Node* second ) const
  {
    // return true if first has lower priority than second.
   //  false otherwise.
  }
};

b. specify the predicate to the priority_queue

typedef std::priority_queue< Node*,  std::vector<Node*>, 
                              compare_node_pointers > my_prioroty_queue ;
// use object(s) of type my_prioroty_queue where required

remember that the predicate must be a relation that is asymetric,
irreflexive and transitive; ie. one that imposes a strict oredering
on the sequence.

vijayan121 1,152 Posting Virtuoso

make your operator< const correct.

bool Node::operator< ( const Node&) const
vijayan121 1,152 Posting Virtuoso

this is what the linux man pages say (in part) about rand(3):

" ... The versions of rand() and srand() in the Linux C Library
use the same random number generator as random() and sran­
dom(), so the lower-order bits should be as random as the
higher-order bits. However, on older rand() implementa­
tions, the lower-order bits are much less random than the
higher-order bits.

In Numerical Recipes in C: The Art of Scientific Computing
(William H. Press, Brian P. Flannery, Saul A. Teukolsky,
William T. Vetterling; New York: Cambridge University
Press, 1992 (2nd ed., p. 277)), the following comments are
made:
"If you want to generate a random integer between 1
and 10, you should always do it by using high-order
bits, as in

j=1+(int) (10.0*rand()/(RAND_MAX+1.0));

and never by anything resembling

j=1+(rand() % 10);

(which uses lower-order bits)."

Random-number generation is a complex topic. The Numeri­
cal Recipes in C book (see reference above) provides an
excellent discussion of practical random-number generation
issues in Chapter 7 (Random Numbers). ..."

vijayan121 1,152 Posting Virtuoso

IMO, sometime STL classes are more hassle than they are worth. One such occassion is during a class when the instructions are to use an array. Another is when the upper bounds of the array are given. And another is when the user has no idea what a template or an iterator is.

ifstream fin("inputFile.txt"); //to read from file
ofstream fout("outputFile.txt"); //to write back to file 
string input[100]; //to hold input
int i = 0;  //to keep track of how many strings actually read in, may be less than max possible.
 
//validate files are open here
 
//read input file one string at a time, adding it to the array in the appropriate index
while(getline(fin, input[i]))
   i++;
 
//write to output file (frontwards for this demonstration) one string per line
for(int x  = 0; x < i; ++x)
      fout << input[i] << endl;
 
//close files here

prefer an array to a vector to bring the all the lines of a text file into memory?
well, i suppose everyone has a right to their opinion.

vijayan121 1,152 Posting Virtuoso

u need to use a vector<string>, not
vector<int>.

and u need to use getline to read in
eah line till eof. the file is read from
begin to end (forward). after inserting
the lines into the vector, iterate
backwards in the vector (from the
last element to the first).

do not worry about the number of
lines (as long as it is not impossibly
large); when u call push_back the
vector resizes itself. start with an
empty vector; after adding all the lines
(push_back), the size() method of the
vector will tell u how many strings have
been added. this is useful if u want to
iterate over it like a c style array; start
with pos size()-1 and end at pos zero
to iterate backwards.

vijayan121 1,152 Posting Virtuoso

to fix the compiler error:
u need to declare the function before u
call it. add the following anywhere before
the call.

void backward(vector <int> vect) ;

a vector is really a dynamically resizeable
array; paasing it by value is not a good
idea at all.
(u are copying a large collection!)
in general, for any user defined type,
prefer passing by const referance instead
of by value. so i would also suggest u
change the signature of backward to

void backward( const vector<int>& vect ) ;

were u not trying to read strings (lines)
from the file (not integers) in the original
post?

vijayan121 1,152 Posting Virtuoso

a. read the lines and insert it into a vector

ifstream file("customer.txt") ;
string rec ;
vector<string> records ;
while( getline(file,rec) ) 
    records.push_back(rec) ;

b. iterate over the vector backwards to
access the redords in reverse order

ofstream outfile("custFileCopy.txt") ;
  std::copy( records.rbegin(), records.rend(),
        std::ostream_iterator<string>(outfile) );

you can do this only if the file is small enough;
for very large files memory may not be sufficient.
u could however read the file in parts (say 1000 records),
create intermediate output files (as above) and then
merge them in reverse order of creation.

*** note: i had not seen Lerner's post; it came in while i was
typing in the reply. so this is just a repetition of what was
suggested in that post

vijayan121 1,152 Posting Virtuoso
vijayan121 1,152 Posting Virtuoso

since we are using std::string, why not

#include <iostream>
#include <string>
using namespace std;
int main()
{
  string str ;  cin >> str ; 
  const string vowels = "aeiouAEIOU" ;
  int n_vowels = 0 ;
  for( string::size_type pos = str.find_first_of(vowels) ; pos != string::npos ;
        pos = str.find_first_of(vowels,pos+1) )  ++n_vowels ;
  cout << "vowels: " << n_vowels  << "\nconsonants: " 
          << str.size()-n_vowels    << '\n' ;
  return 0 ;
}
~s.o.s~ commented: Yes a good approach but too much for a beginner..;) - ~s.o.s~ +15
vijayan121 1,152 Posting Virtuoso

Anyone who considers arithmetical methods of producing random digits is, of course, in a state of sin - John Von Neumann (1951).

for more information see:
http://www.random.org/randomness/

if pseudo-randomness is all that is required, a good c++ library is
the boost random number library.
for more information on these, see
http://www.boost.org/libs/random/random-generators.html
http://www.boost.org/libs/random/random-distributions.html
http://www.boost.org/libs/random/random-concepts.html

vijayan121 1,152 Posting Virtuoso
vijayan121 1,152 Posting Virtuoso

Index = 1;
should be inside the outer while loop.

vijayan121 1,152 Posting Virtuoso

for your specific problem:
1-100 arrays of size 10 with randomly distinct numbers from (0-9)
2-100 arrays of size 50 with randomly distinct numbers from (0-49)
3-100 arrays of size 100 with randomly distinct numbers from (0-99)
4-100 arrays of size 200 with randomly distinct numbers from (0-199)

u could fill an array of size N with values
0, 1, 2, ..., N-2, N-1
and then just do a std::random_shuffle on it.
(after seeding the random number generator)

Salem commented: Excellent suggestion, but probably too advanced to hand in as noob homework +6
vijayan121 1,152 Posting Virtuoso

u could

std::set<int> unique_ints ;
// N == number of elements
// MAX_VALUE == max value of an element
while( unique_ints.size() < N )
   unique_ints.insert( std::rand()%MAX_VALUE ) ;
//iterate from unique_ints.begin() to 
// unique_ints.end() and populate the array
vijayan121 1,152 Posting Virtuoso

a. you should be able to get a more accurate output by using cout << fixed << setprecision(5).

b. the accuracy of the mantissa of a floating point value on a c++ implementation can be gauged from std::numeric_limits<float>::digits.
rough accuracy for reasonable small values would be within += std::numeric_limits<float>::epsilon()