What is C++ comparing when comparing two different strings? - c++

Code below when I check if K or Y is greater, what method is used to compare two different strings? number of bits?
#include <iostream>
#include <string>
using namespace std;
int main() {
string y = "can't";
string k = "solve";
if(k > y){
cout << "k is bigger";
}else {
cout << "y is bigger";
}
return 0;
}
k is bigger

string compare is a lexigraphical comparison:
All comparisons are done via the compare() member function (which
itself is defined in terms of Traits::compare()):
Two strings are equal if both the size of lhs and rhs are equal and
each character in lhs has equivalent character in rhs at the same
position.
The ordering comparisons are done lexicographically -- the comparison
is performed by a function equivalent to std::lexicographical_compare.
And this is how lexigraphical comparison works:
A lexicographical comparison is the kind of comparison generally
used to sort words alphabetically in dictionaries; It involves
comparing sequentially the elements that have the same position in
both ranges against each other until one element is not equivalent to
the other.

These relational operators are overloaded in the header file string.
All the relational operators used for string operations can be found in the link below.
http://www.cplusplus.com/reference/string/string/operators/
Hope this clears your doubt.

Related

How do the ">" and "<" operators work for string comparisons?

In the C++ textbook I'm reading (Programming, Principles and Practice using C++ by Bjarne Stroustrup), there are numerous instances of code snippets in which strings are compared as follows:
if (str1 > str2) and then some code.
Could someone please explain to me how "bigger than" and "less than" operators work in conjunction with strings declared as follows:
#include <string>
.
.
.
string str1 = "foo";
string str2 = "bar";
I've tried searching on Stack Overflow and on others for this answer, but to no avail.
The strings are compared lexicographically . The string in which an character is lexicographically greater than the corresponding character in other string will be considered as the greater string. This is known as lexicographical comparison.
The lexicographic or lexicographical order (also known
as lexical order, dictionary order, alphabetical order or
lexicographic(al) product) is a generalization of the way words are
alphabetically ordered based on the alphabetical order of their
component letters.
You can use the .compare() method as well to compare two strings . It will return the following values -
0 : They compare equal
Less than 0 : Either the value of the first character that does not
match is lower in the compared string, or all compared characters
match but the compared string is shorter.
more than 0 : Either the value of the first character that does not
match is greater in the compared string, or all compared characters
match but the compared string is longer.
On the contrary, the relational operators (like >, <, ==) will return only boolean values true of false. In the expression str1 < str2 , str1 will be smaller than str2 if first mismatched character in str1 is smaller than the corresponding character in str2. If all characters match, str1 will be less than str2 only if its length is shorter.
Relational operators on strings estabilish so-called lexicographical order. It's the same ordering as used in the dictionaries.
Here's the algorithm: to determine if a is less than b, you need to find the smallest i so that a[i] != b[i], and if (unsigned char)a[i] < (unsigned char)b[i], then a < b, otherwise a > b.
If there is no such i, then a == b.
If a is a prefix of b, then a < b (this follows from the algorithm above, if you consider the extra \0 at the end of a string to be a part of the string).

How does s.compare member function behave in the C++ code below?

I have this C++ code below to solve for a homework and after I ran it with Code::Blocks, it tells me that i=0, which means the expression s.compare(t)<0 is false. But, the way I see it, it's the other way around: (s<t, because AbcA < AAbcA). Can someone please explain it to me?
#include <iostream>
#include <string>
using namespace std;
int main(void) {
string s = "Abc", t = "A";
s=s+t;
t=t+s;
int i = s.compare(t)<0;
int j = s.length()<t.length();
cout<<i+j<<endl;
return 0;
}
According to the reference std::string::compare returns:
negative value if *this appears before the character sequence specified by the arguments, in lexicographical order
zero if both character sequences compare equivalent
positive value if *this appears after the character sequence specified by the arguments, in lexicographical order
Lexicographical comparison being defined as:
Lexicographical comparison is a operation with the following properties:
Two ranges are compared element by element.
The first mismatching element defines which range is lexicographically less or greater than the other.
If one range is a prefix of another, the shorter range is lexicographically less than the other.
If two ranges have equivalent elements and are of the same length, then the ranges are lexicographically equal.
An empty range is lexicographically less than any non-empty range.
Two empty ranges are lexicographically equal.
"AbcA" comes lexicographically after "AAbc", because the first nonequal character 'b' (ASCII 0x62) comes after 'A' (ASCII 0x41)

Find All Palindrome Substrings in a String by Rearranging Characters

For fun and practice, I have tried to solve the following problem (using C++): Given a string, return all the palindromes that can be obtained by rearranging its characters.
I've come up with an algorithm that doesn't work completely. Sometimes, it finds all the palindromes, but other times it finds some but not all.
It works by swapping each adjacent pair of characters N times, where N is the length of the input string. Here is the code:
std::vector<std::string> palindromeGen(std::string charactersSet) {
std::vector<std::string> pals;
for (const auto &c : charactersSet) {
for (auto i = 0, j = 1; i < charactersSet.length() - 1; ++i, ++j) {
std::swap(charactersSet[i], charactersSet[j]);
if (isPalandrome(charactersSet)) {
if (std::find(pals.begin(), pals.end(), charactersSet) == pals.end()) {
// if palindrome is unique
pals.push_back(charactersSet);
}
}
}
}
return pals;
}
What's the fault in this algorithm? I'm mostly concerned about the functionality of the algorithm, rather than the efficiency. Although I'll appreciate tips about efficiency as well. Thanks.
This probably fits a bit better in Code Review but here goes:
Logic Error
You change charactersSet while iterating over it, meaning that your iterator breaks. You need to make a copy of characterSet, and iterate over that.
Things to Change
Since pals holds only unique values, it should be a std::set instead of a std::vector. This will simplify some things. Also, your isPalandrome method spells palindrome wrong!
Alternative Approach
Since palindromes can only take a certain form, consider sorting the input string first, so that you can have a list of characters with an even number of occurrences, and a list of characters with an odd number. You can only have one character with an odd number of occurrences (and this only works for an odd length input). This should let you discard a bunch of possibilities. Then you can work through the different possible combinations of one half of the palindrome (since you can build one half from the other).
Here is another implementation that leverages std::next_permutation:
#include <string>
#include <algorithm>
#include <set>
std::set<std::string> palindromeGen(std::string charactersSet)
{
std::set<std::string> pals;
std::sort(charactersSet.begin(), charactersSet.end());
do
{
// check if the string is the same backwards as forwards
if ( isPalindrome(charactersSet))
pals.insert(charactersSet);
} while (std::next_permutation(charactersSet.begin(), charactersSet.end()));
return pals;
}
We first sort the original string. This is required for std::next_permutation to work correctly. A call to the isPalindrome function with a permutation of the string is done in a loop. Then if the string is a palindrome, it's stored in the set. The subsequent call to std::next_permutation just rearranges the string.
Here is a Live Example. Granted, it uses a reversed copy of the string as the "isPalindrome" function (probably not efficient), but you should get the idea.

How can I compare if a char is higher or lower in alphabetical order than another?

Pretty much as the title. I'm writing a linked list and I need a function to sort the list alphabetically, and I'm pretty stumped. Not sure how this has never come up before, but I have no idea how to do it other than to create my own function listing the entire alphabet and comparing positions of letters from scratch.
Is there any easy way to do this?
Edit for clarity:
I've got a linear linked list of class objects, each class object has a char name, and I'm writing a function to compare the name of each object in the list, to find the highest object alphabetically, and then find the next object down alphabetically, etc, linking them together as I go. I already have a function that does this for an int field, so I just need to rewrite it to compare inequalities between alphabetical characters where a is largest and z is smallest.
In hindsight that was probably a lot more relevant than I thought.
I think a couple of the answers I've gotten already should work so I'll pop back and select a best answer once I've gotten it working.
I'm also working with g++ and unity.
I think that in general case the best approach will be to use std::char_traits:
char a, b;
std::cin >> a >> b;
std::locale loc;
a = std::tolower(a, loc);
b = std::tolower(b, loc);
std::cout << std::char_traits::compare(&a, &b, 1u);
But in many common situations you can simply compare chars as you do it with other integer types.
My guess is that your list contains char* as data (it better contain std::strings as data). If the list is composed of the latter, you can simply sort using the overloaded std::string's operator<, like
return str1 < str2; // true if `str1` is lexicographically before `str2`
If your list is made of C-like null-terminated strings, then you can sort them using std::strcmp like
return std::strcmp(s1, s2);
or use the std::char_traits::compare (as mentioned by #Anton) like
return std::char_traits<char>::compare(s1, s2, std::min(std::strlen(s1), std::strlen(s2)));
or sort them via temporary std::strings (most expensive), like
return std::string(s1) < std::string(s2); // here s1 and s2 are C-strings
If your list simply contains characters, then, as mentioned in the comments,
return c1 < c2; // returns true whenever c1 is before c2 in the alphabet
If you don't care about uppercase/lowercase, then you can use std::toupper to transform the character into uppercase, then always compare the uppercase.
#include <stdio.h>
#include <ctype.h>
void main(void) {
char a = 'X', b = 'M';
printf("%i\n", a < b);
printf("%i\n", b < a);
printf("%i\n", 'a' < 'B');
printf("%i\n", tolower('a') < tolower('B'));
}
prints out:
0
1
0
1
chars are still numbers, and can be compared as such. The upper case letters and lower case letters are all in order, with the upper case letters before the lower. (Such that 'Z' < 'a'.) See an ASCII table.
As you can see from this ASCII table, all of the alphanumeric characters appear in the correct alphabetical order, regarding their actual values:
"Is there any easy way to do this?"
So yes, comparing the character values will provide to have them sorted in alphabetical order.
would something like below suffice ? convert everything to upper first.
class compareLessThanChar{
public:
bool operator()(const char a, const char b)
{ return toupper(a) < toupper(b); }
}
std::multiset<char, compareLessThanChar> sortedContainer;

Does hash_map automatically sort [C++]?

In the below code, hash_map is automatically sorting or maybe inserting elements in a sorted order. Any ideas why it does this?? Suggestions Please??
This is NOT a homework problem, trying to solve an interview question posted on glassdoor dot com.
#include <iostream>
#include <vector>
#include <ext/hash_map>
#include <map>
#include <string.h>
#include <sstream>
using namespace __gnu_cxx;
using namespace std;
struct eqstr
{
bool operator()(int i, int j) const
{
return i==j;
}
};
typedef hash_map<int, int, hash<int>, eqstr> myHash;
int main()
{
myHash array;
int inputArr[20] = {1,43,4,5,6,17,12,163,15,16,7,18,19,20,122,124,125,126,128,100};
for(int i=0;i<20;i++){
array[inputArr[i]] = inputArr[i]; //save value
}
myHash::iterator it = array.begin();
int data;
for (; it != array.end(); ++it) {
data = it->first;
cout << ":: " << data;
}
}
//!Output ::: 1:: 4:: 5:: 6:: 7:: 12:: 15:: 16:: 17:: 18:: 19:: 20:: 43:: 100:: 122:: 124:: 125:: 126:: 128:: 163
Hash map will not automatically sort your data. In fact the order is unspecified, depending on your hash function and input order. It is just that in your case the numbers turns out are sorted.
You may want to read about hash table for how this container stores the data.
A clear counter example can be created by replacing that 100 with 999999999. The result is
:: 1:: 4:: 5:: 6:: 7:: 12:: 15:: 16:: 17:: 18:: 19:: 20:: 999999999:: 43:: 122:: 124:: 125:: 126:: 128:: 163
(The actual reason is the hash_map's bucket_count is 193 and the hash function of int is an identity function, so any numbers below 193 will appear sorted.)
A hash map may appear to be sorted based on a few factors:
The hash function returns values that are in the same order as the input, for the range of input that you are providing.
There are no hash collisions.
There are no guarantees that the results will be sorted, it's only a coincidence if they come out that way.
Think about how the hash function operates. A hash is always a function f:input->output that maps the input set I into a (usually smaller) output set O so that the input set is approximately uniformly distributed across the output set.
There is no requirement that order should be preserved; in fact, it's unusual that it would be preserved, because (since the output set is smaller) there will be values *i,j*that have the same hash. This is called a collision.
On the other hand, there's no reason it shouldn't. IN fact, it can be proven that there will always exist at least one sequence that will preserve the order.
But there's another possibility: if ALL the values collide, then they get stored in some other kind of data structure, like a list. It may be that these all collidge, and the other structure imposes order.
Three possibilities: hash_map happens to sort that particular sequence, or hash_map is actually implimented as an array, or the values collidge and the implementation stores collisions in a way that gives a sorted order.