How to compare two strings that are different sizes - c++

Lets just say string A = "ABCDEF", string B = "ABC"
Is there a way to compare both these strings character by character?
For example:
Lets say you wanted to iterate through each string,
for(size of strings)
if(A.at(i) == B.at(i)
{
do something
}
else
{
do something else
}
You couldn't do it in a for loop since they're different sizes, any other suggestions?

You couldn't do it in a for loop since they're different sizes,
You absolutely can do it in a loop. You can use the following algorithm:
Compare lengths of the strings
Store the shorter length in n
Do n iterations in loop
Decide what you want to do with rest of the longer string

You could also take a look at something like std::lexicographical_compare. It is used to sort words as they would be sorted in the dictionary. If you want to ensure that characters themselves are sorted in a different order, you can provide a function that does that comparison. For example, let's imagine that you want a letter 'c' to actually be sorted as a 'k'. You can accomplish that in the following manner:
bool comp(char c1, char c2)
{
c1 = std::tolower(c1);
c2 = std::tolower(c2);
c1 = (c1=='c') ? 'k' : c1;
c2 = (c2=='c') ? 'k' : c2;
return c1 < c2;
}
// main.cpp
std::string str1 = "string c";
std::string str2 = "string d";
std::string str3 = "string k";
std::cout << std::boolalpha;
std::cout << str1 << ( std::lexicographical_compare(str1, str2, comp) ? "<" : ">=" ) << str2 << std::endl;
std::cout << str1 << ( std::lexicographical_compare(str1, str3, comp) ? "<" : ">=" ) << str3 << std::endl;
std::cout << str2 << ( std::lexicographical_compare(str2, str3, comp) ? "<" : ">=" ) << str3 << std::endl;

if you use std::string, for comparison you can either use the compare function or use relational operators, provided with this class.
std::string str1 ("green apple");
std::string str2 ("red apple");
if (str1.compare(str2) != 0)
std::cout << str1 << " is not " << str2 << '\n';
or
if (str1 != str2) std::cout << "str1 and str2 are not equal\n";
all other relational operators, i.e., == < > <= >= are also available. It looks like in your case you only need == of !=.
if you insist on comparing strings char by char, than you can do it in a loop in several ways. For example,
bool equal = true;
if (str1.length() != str2.length())
equal = false;
else
for (int i = 0; equal && i < str1.length(); i++)
if (str1.at(i) != str2.at(i)
equal = false;

Related

Why is this boost::container::string & std::string comparison not working as intended?

Say you have a std::string and a boost::container::string just like this :
std::string stdString = "This is a test";
boost::container::string boostString = "This is a test";
Say you want to compare their content ; the following is not possible because we cannot compare their types :
stdString == boostString // no operator "==" matches these operands
You then choose to use both of their methods .c_str() to get a char* from each string. Not being sure if this does effectivly compare the strings, you try it :
stdString.c_str() == boostString.c_str() // compiles, but comparison returns false
You then try to only use c_str() method from the std::string :
stdString.c_str() == boostString // compiles, and comparison seems fine
You try the opposite out of curiosity and it works as well :
stdString == boostString.c_str() // compiles, and comparison seems fine
So the question is, why does these two latter comparisons seem to work fine when the first one did not ?
Bonus question : Is this an unreliable way of comparing the content of these strings ?
Full code sample :
#include <boost/container/string.hpp>
#include <iostream>
int main(int argc, char *argv[])
{
std::string stdString = "This is a test";
boost::container::string boostString;
for (int i = 0; i < 2; ++i)
{
if (i == 0)
{
boostString = "This is a test";
std::cout << "Both strings have the same content." << std::endl << std::endl;
}
else
{
boostString = "This is z test";
std::cout << std::endl << std::endl;
std::cout << "Both strings are different from each other." << std::endl << std::endl;
}
std::cout << "stdString.c_str() == boostString.c_str() comparison is : ";
if (stdString.c_str() == boostString.c_str())
std::cout << "true" << std::endl;
else
std::cout << "false" << std::endl;
std::cout << "stdString.c_str() == boostString comparison is : ";
if (stdString.c_str() == boostString)
std::cout << "true" << std::endl;
else
std::cout << "false" << std::endl;
std::cout << "stdString == boostString.c_str() comparison is : ";
if (stdString == boostString.c_str())
std::cout << "true" << std::endl;
else
std::cout << "false" << std::endl;
}
return 0;
}
Output given by the sample :
> Both strings have the same content.
>
> stdString.c_str() == boostString.c_str() comparison is : false
> stdString.c_str() == boostString comparison is : true
> stdString == boostString.c_str() comparison is : true
>
>
> Both strings are different from each other.
>
> stdString.c_str() == boostString.c_str() comparison is : false
> stdString.c_str() == boostString comparison is : false
> stdString == boostString.c_str() comparison is : false
With stdString.c_str() == boostString.c_str() you don't compare the strings, you compare the pointers returned by each objects c_str function. And they will most certainly not be equal. If you want to compare strings C-style use std::strcmp.
The reason e.g. stdString.c_str() == boostString works is because boost::container::string have a non-explicit constructor taking a const char* argument, just what stdString.c_str() is returning. That means stdString.c_str() == boostString is actually equal to boost::container::string(stdString.c_str()) == boostString, which compares two boost::container::string objects.
Same for stdString == boostString.c_str(), it's equal to stdString == std::string(boostString.c_str()).
If you need to mix std::string and boost::container::string, and need to use some specific operators with that mix, then you can always overload those operators yourself.
For example
bool operator==(std::string const& stdString, boost::container::string const& boostString)
{
// If the length of the strings differs, then they're not equal and we return false
// Otherwise, compare the actual contents of the strings
return stdString.length() == boostString.length() &&
std::memcmp(stdString.c_str(), boostString.c_str(), stdString.length()) == 0;
}
bool operator==(boost::container::string const& boostString, std::string const& stdString)
{
return stdString == boostString; // Calls the previously defined operator== overload
}
Both are needed so you can use either type on either side of ==.
Also note that I'm using std::memcmp for the comparison, because either string could contain embedded zeros, which would otherwise act as the string terminator for std::strcmp.

How to compare elements of a vector against each other? C++

I am supposed to read some data (specifically string datatype) and store each element in a vector. Now I have to check if any of the different strings that were inputted match in size, and if they do I have to see if there are any matching letters. Now my question is how do I compare what's inside the vector (first the size and then the different letters). Is it possible?
Say I have
HELLO
and
HELLA
They have the same size, and 4 letters that match.
This is what I am trying to accomplish.
The code that I have does not work given my ignorance about the matter.
Thank you in advance.
vector <string> myVector;
//insert data insdide of the vector
myVector.push_back("Hello");
myVector.push_back("Hello");
myVector.push_back("Hello2");
myVector.push_back("Hello3");
myVector.push_back("Hello4");
//This is wrong
for (unsigned int i = 0; i < myVector.size(); i++) {
if (myVector[i].size == myVector[i+1].size()){
cout << "SAME SIZE" << endl;
}
}
return 0;
You just have make a simple mistake for size() function and you are trying to access the element which is not present by using i+1 for last iteration.
So just change your for loop just as below
for (unsigned int i = 1; i < myVector.size(); i++)
{
if (myVector[i].size() == myVector[i-1].size()) // .size() should be used
{
cout << "SAME SIZE" << endl;
}
}
Here's a way of writing it:
// returns true if #param s1 and #param s2 are equal in letters
bool isEqual(const string& s1, const string& s2) {
if(s1.size() != s2.size())
return false;
bool equal = false;
// iterates over all the characters in s1 and s2 and compare them
for(auto ch1 = s1.cbegin(), ch2 = s2.cbegin(); ch1 != s1.cend(),ch2!= s2.cend(); ch1++, ch2++) {
if(*ch1 == *ch2)
equal = true;
else
return false;
}
return equal;
}
// type of iter is vector<string>::const_iterator meaning it can only read the value
for (auto iter = myVector.cbegin(); iter != myVector.cend() - 1; iter++){
if(isEqual(*iter, *(iter + 1)))
std::cout << *iter << " equal " << *(iter + 1) << endl;
else
std::cout << *iter << " different " << *(iter + 1) << endl;
}
Here, I used iterators(you should write code in modern C++, avoid using subscript).

C++ Strings Matching Returning False

I'm working on my C++ assignment. I'm having an issue with string comparison.
I'm comparing two apparently identical strings using == operating but the condition returns false. The debugger also shows that both strings (stored in different variables) are identical. I must be missing something.
Here is my code:
void classCounter() {
ifstream fread;
string linetxt;
char *records[50];
char myLine[100];
char delims[] = "|";
int btotal=0,etotal=0,total=0;
fread.open("F:\\myfile.txt");
while(!fread.eof()) {
getline(fread,linetxt,'\n');
int i = 0;
strcpy(myLine, linetxt.c_str());
records[i] = strtok( myLine, delims );
while( records[i] != NULL )
{
cout << records[i] << "|";
char *bu = "Business";
if(records[i] == bu) {
btotal++;
}
if(records[i] == "Economy") {
etotal++;
}
//printf("%d '%s'\n", i, records[i]);
records[++i] = strtok( NULL, delims );
break;
}
total++;
}
cout << "Total number of booked Business seats: " << btotal << endl;
cout << "Total number of booked Economy seats: " << etotal << endl;
cout << "Total number of booked seats: " << total << endl << endl;
}
Here is what debugger shows:
Both if conditions are returning false.
Please suggest what could be the issue.
You are comparing two pointers, and they will never be the same. Either heed the advice to use std::string (what I recommend too) or you use strcmp to compare strings.
if(records[i] == bu) {
and
if(records[i] == "Economy") {
compare two char*, not strings.
You can compare them as strings by using std::string or using the function strcmp.
Option 1: Use std::string
std::string records[50];
With that change,
if(records[i] == bu) {
and
if(records[i] == "Economy") {
should work.
Option 2: Use strcmp
if( strcmp(records[i], bu) == 0) {
and
if( strcmp(records[i], "Economy") == 0) {
Your debugger is telling you what you need to know.. You're using char* instead of String so your char* are pointers. Your program is comparing two pointers and 0x00c93bc0 != 0x002af824.
Use strcmp in the future to avoid this problem
So I'm going to assume your input file looks something like:
Business|Economy|Economy|Economy|Business
Economy|Economy|Economy|Business|Economy
...and so on. Correct? And you're trying to count up how many of each kind of ticket was sold?
If so, I'd write the code quite a bit differently. I'd probably do something like this:
std::map<std::string, int> tickets;
std::string name;
std::ifstream in("f:/myfile.txt");
int total = 0;
while (std::getline(in, name, '|')) {
++tickets[name];
++total;
}
for (auto t : tickets)
std::cout << "Total number of booked " << t.first << " seats is: " << t.second "\n";
std::cout << "Total number of booked tickets: " << total << "\n";

converting string to time for comparison

I have two strings srt1 and str2 as:
std::string str1 = "20110627120000";
std::string str2 = "20110629120000";
All I need is to convert them into time format and compare which one is greater.
And I am using below code for it but I am getting segmentation fault:
tm tm1,tm2;
sscanf(str1.c_str(),"%4d%2d%2d %2d%2d%2d",&tm1.tm_year,&tm1.tm_mon,&tm1.tm_mday,&tm1.tm_hour,&tm1.tm_min,&tm1.tm_sec);
sscanf(str2.c_str(),"%4d%2d%2d %2d%2d%2d",&tm2.tm_year,&tm2.tm_mon,&tm2.tm_mday,&tm2.tm_hour,&tm2.tm_min,&tm2.tm_sec);
std::cout << "5 \n";
if ((tm1.tm_year < tm2.tm_year) && (tm1.tm_mon<tm2.tm_mon) && (tm1.tm_mday<tm2.tm_mday ))
{
std::cout << str2 <<"is greater \n";
}
Why do you convert the strings when they are perfectly comparable?
int main()
{
std::string str1 = "20110627120000";
std::string str2 = "20110629120000";
std::cout << ((str1 < str2) ? "True" : "False") << std::endl;
}
Using sscanf with the format having a space in between "%4d%2d%2d %2d%2d%2d" looks plain wrong. Not checking the result of it, is.
Dates in the format you specified can be easily converted to integers and then compared. See below:
#include <iostream>
int main()
{
unsigned long long date_a = std::stoull("20110627120000");
unsigned long long date_b = std::stoull("20110629120000");
std::cout << std::max(date_a, date_b) << std::endl;
return 0;
}

Case sensitive string comparison in C++

Can anyone pls let me know the exact c++ code of case sensitive comparison function of string class?
How about?
std::string str1, str2;
/* do stuff to str1 and str2 */
if (str1 == str2) { /* do something */ }
Or
if (str1.compare(str2) == 0) { /* the strings are the same */ }
std::string str1("A new String");
std::string str2("a new STring");
if(str1.compare(str2) == 0)
std::cout<<"Equal"; // str1("A new String") str2("A new String");
else
std::cout<<"unEqual"; //str1("A new String") str2("a new STring")
compare() returns an integral value rather than a boolean value. Return value has the following meaning: 0 means equal, a value less than zero means less than, and a value greater than zero means greater than
== is overloaded for string comparison in C++ AFAIK (unlike in Java, where u have to use myString.equals(..))
If you want to ignore case when comparing, just convert both strings to upper or lower case as explained here: Convert a String In C++ To Upper Case
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str1 ("green apple");
string str2 ("red apple");
if (str1.compare(str2) != 0)
cout << str1 << " is not " << str2 << "\n";
if (str1.compare(6,5,"apple") == 0)
cout << "still, " << str1 << " is an apple\n";
if (str2.compare(str2.size()-5,5,"apple") == 0)
cout << "and " << str2 << " is also an apple\n";
if (str1.compare(6,5,str2,4,5) == 0)
cout << "therefore, both are apples\n";
return 0;
}
I got it from http://www.cplusplus.com/reference/string/string/compare/
Hope google work !!
But use == operator like
s1 == s2 would also work good