1

I know that in java there is a compareTo method that you can write in a class that will compare two variables and return a value -1, 1, or 0 signifing greater than, less than, and equal to operations. Is there a way to do this in C++?

Background: Im creating a modified string class in which it takes a string and an arraylist. I want to be able to compare the string in a traditional fashion where if its lower in the alphabet it will be less than, than higher it would be greater than. Than i just want the array list to be linked to the files to store pages in which the word was indexed on in a text file. Anyways the specifics do not matter since i already have the class written. I just need to create compareTo method that would be able to be used in the main of my cpp file or by other data type like various trees for instance.

Ill write the code in java as i know how and maybe someone can help me with C++ Syntax (im required to write in c++ for this project unfortunatly, and i am new to C++)

I will shorten the code to give the rough outline of what im doing than write the compareTo method as i know how in java

class name ModifiedString
Has variables: word , arraylist pagelist
Methods: 
getWord (returns the word associated with the class, i.e its string)
appendPageList (adds page numbers to the array list, this doesnt matter in this question)

Hers how i would do it in java

int compareTo(ModifiedString a){
  if(this.getWord() > a.getWord())
      return 1;
  else if (this.word() < a.getWord())
      return -1;
  else return 0;
}

Then when < , > , or == is used on a ModifiedWord than the operations would be valid.

T.V.
  • 505
  • 3
  • 10
user2665682
  • 95
  • 1
  • 4
  • 12

4 Answers4

2

std::string already includes a working overload of operator<, so you can just compare strings directly. Java uses compareTo primarily because the built-in comparison operator produces results that aren't generally useful for strings. Being a lower-level language, Java doesn't support user-defined operator overloads, so it uses compareTo as a band-aid to cover for the inadequacy of the language.

From your description, however, you don't need to deal with any of that directly at all. At least as you've described the problem, you really want is something like:

std::map<std::string, std::vector<int> > page_map;

You'll then read words in from your text file, and insert the page number where each occurs into the page map:

page_map[current_word].push_back(current_page);

Note that I've used std::map above, on the expectation that you may want ordered results (e.g., be able to quickly find all words from age to ale in alphabetical order). If you don't care about ordering, you may want to use std::unordered_map instead.

Edit: here's a simple text cross-reference program that reads a text file (from standard input) and writes out a cross-reference by line number (i.e., each "word", and the numbers of the lines on which that word appeared).

#include <map>
#include <unordered_map>
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <iterator>
#include "infix_iterator.h"

typedef std::map<std::string, std::vector<unsigned> > index;

namespace std {
ostream &operator<<(ostream &os, index::value_type const &i) { 
    os << i.first << ":\t";
    std::copy(i.second.begin(), i.second.end(),
        infix_ostream_iterator<unsigned>(os, ", "));
    return os;
}
}

void add_words(std::string const &line, size_t num, index &i) { 
    std::istringstream is(line);
    std::string temp;

    while (is >> temp)
        i[temp].push_back(num);
}

int main() { 
    index i;
    std::string line;
    size_t line_number = 0;

    while (std::getline(std::cin, line))
        add_words(line, ++line_number, i);

    std::copy(i.begin(), i.end(), 
        std::ostream_iterator<index::value_type>(std::cout, "\n"));
    return 0;
}

If you look at the first typedef (of index), you can change it from map to unordered_map if you want to test a hash table vs. a red-black tree. Note that this interprets "word" pretty loosely -- basically any sequence of non-whitespace characters, so for example, it'll treat example, as a "word" (and it'll be separate from example).

Note that this uses the infix_iterator I've posted elsewhere.

Community
  • 1
  • 1
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • This actually makes a lot of sense to me instead of creating a whole class which maps a vector to the string that way. So in that case i would be adding maps (of strings and vectors) to a tree or hashtable (which is what i want to do) than when i do a find operations (in this case i have it defined to return the data) it will return a map. From which i can access the pages. However when doing comparisons in a tree will the map compare the strings or the vector? Pretty much all i need to be doing in this exercise is to store words with an index of page numbers it occurs on using different trees – user2665682 Nov 15 '13 at 16:36
  • Why would you add the map to a tree or hashtable? The map *is* a tree (and unordered_map is a hash table). It already takes you directly from word to page number(s). – Jerry Coffin Nov 15 '13 at 17:19
  • I have already constructed a redblacktree, binarytree, hashtable, chainedhashtable and a few more data structures. All of these have their own adds,removes, and finds that take a paramete T x so it can be used in any case. Thats why i though creating my own data type which stores a string and an array was the best option, i dont know how to compare though. The idea is to index the words using each of these data structures (So i can change in between then than observe the running times of each data structure) and add an array ossociated with the word that stores the page numbers it occures on. – user2665682 Nov 15 '13 at 17:35
  • @user2665682: Just compare using `<`, as in `if (string1 < string2)...` I'd probably write the others to work (externally) like `std::map`, making substitution easy. – Jerry Coffin Nov 15 '13 at 17:46
  • Ok, so in my ModifiedString how should make it compare the modifiedStrings .getWord (which returns a string) so lets say i have test which is a modified string, then i can call if(string > test) where test returns test.getWord() by default so i dont have to write test.getWord in place of test every time since my other data structures wont allow it. This idea of operator overloading is just confusing be a bit since its totally new to me. – user2665682 Nov 15 '13 at 17:56
  • @user2665682: My immediate impression is that you're making this a lot more complex than necessary. I've updated the answer to give some idea of how this can work with the built-in string and map/unordered_map types. – Jerry Coffin Nov 15 '13 at 18:48
0

There is no standard way in C++ to define an operator that does what the Java compareTo() function does. You can, however, implement

int compareTo(const ModifiedString&, const ModifiedString&);

Another option is to overload the <, <=, >, >=, == and != operators, e.g. by implementing

bool operator<(const ModifiedString&, const ModifiedString&);
Oswald
  • 31,254
  • 3
  • 43
  • 68
  • Even if you suggest to use a Java-like solution (I mean the first solution, the `compareTo()` method) which is not the way that C++ works, provide a well defined solution: If you implement a binary `compareTo()`, specify that it should be `static`, or simply implement a member one-parameter `compareTo()` function exactly as Java does. Note that is a suggestion, not a critic. – Manu343726 Nov 15 '13 at 16:30
  • The canonical name in C++ is `compare`, as in `std::string::compare`. – Pete Becker Nov 15 '13 at 16:49
0

In C++, you define bool operator< directly, no need to invent funny names, same for operator< and operator==. They're generally implemented as member functions taking one extra argument, the righthand side, but you could also define them as non-member functions taking two arguments.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • *" They're generally implemented as member functions taking one extra argument, the righthand side, "* I've always heard that `friend` non-member overload is preferable to member, because it allows you to specify first non-class operand, like [this answer](http://stackoverflow.com/a/4622467/1609356) explains. – Manu343726 Nov 15 '13 at 16:21
  • @Manu343726: It's more of an issue for other operators. `<` usually has no overloads with non-class left hand sides. The obvious exception is `"" == std::string()`. – MSalters Nov 15 '13 at 16:28
0

Sun decided to not include operator overloading in Java, so them provided an in-class way (through member functions) to do that job: The equals() and compareTo() functions.

C++ has operator overloading, which allows you to specify the behaviour of the language operators within your own types.

To learn how to overload operators, I suggest you to read this thread: Operator overloading

Community
  • 1
  • 1
Manu343726
  • 13,969
  • 4
  • 40
  • 75