Comparing two strings without using strcmp [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
This is my question:
Write a function name compareStrings(char * str1, char * str1, int i=0), which returns decides whether
the two received string are equal or not. The third parameter decides whether to take case
sensitiveness while comparing strings: 0 means case sensitive, otherwise case sensitive.
The function returns 0 if two strings are equal
Returns 1 if str1 > str2
Returns -1 if str1 < str2.
Example:
compareStrings( “apple”, “Apple” ) returns 1
compareStrings( “apple a day keeps the doctor away”, “apple are good for health” ) returns -1
This code I have done yet but it is not comparing all Ascii's. According to me I must put all Ascii's checks but it would be so long
Please tell me any other logic regarding this Question.
#include<iostream>
using namespace std;
int compareStrings(char * str1, char * str2);
int main()
{
char str1[]="apple";
char str2[]="Apple";
int ret;
ret=compareStrings(str1,str2);
if(ret==0)
cout<<"Both strings are equal"<<endl;
else if(ret==1)
cout<<"string 1 is bigger than 2"<<endl;
else
cout<<"string 1 is lower than 2"<<endl;
return 0;
}
int compareStrings(char * str1, char * str2)
{
for(int i=0;i<20;i++)
{
if(str1[i]==str2[i])
return 0;
else if(str1[i] >= 'A' && str1[i] <= 'Z' &&str2[i] <='a' && str2[i]<='z')
return -1;
else if(str2[i] >= 'A' && str2[i] <= 'Z' &&str1[i] <='a' && str1[i]<='z')
return 1;
}
}

There are multiple problems with the code as shown. I'm ignoring the fact that you aren't using C++ std::string type, though that is another issue.
You only compare the first twenty characters of the strings.
What happens if the strings are longer?
What is the return value from the function if the loop ends?
You compare the first twenty characters of the strings even if the strings are shorter.
You return 0 on the first character that's the same.
You return -1 if the current character in the first string is upper-case and the current character in the second is lower-case, regardless of whether the case-sensitivity flag is set or whether the letters are equivalent.
Similarly you return +1 for the converse condition.
You don't use the isalpha(), isupper(), islower() macros (prefixed with std:: from <cctype> or equivalent functions.
You don't recognize that if one string contains a 7 and the other a 9, you should come to a decision.
Since the comparison function is not supposed to modify either string, the function prototype should use const char * arguments.
Etc.
You will need to rethink your code rather carefully. Ignore case-insensitivity until you have case-sensitive comparisons working correctly. Then you can modify it to handle case-insensitive comparisons too.

Related

Doing a scenario problem in C++ and am unsure of how to proceed with boolean and if-loops

**This is a translation, very hastily written. If you need any clarification, just comment.
The question given is:
We live in a world with too much garbage. We have found a way to compress the garbage, but it can only be done in a specific way, or else the garbage will explode. The garbage has to be laid out in a line, and it can only be compressed with its neighbor, and only if its neighbor has the same value as it.
The first input is int N, and it represents the amount of garbage in the row. The second input is t, and it must have an input of as many characters as the value in N. If the whole thing is able to be compressed until there's only 1 garbage (t) left, then the output will be "YES".
We've figured out that as long as either N == 1, or all inputs in t (all the characters) are the same, the output will be YES.
Example inputs/outputs:
Input:
2
1 1
Output:
YES
Or
Input:
3
1 2 1
Output:
NO
Or
Input:
1
5
Output:
YES
Here's what we've got so far:
#include <iostream>
#include <string>
using namespace std;
int N;
string t;
bool allCharactersSame(string s)
{
int n = s.length();
for (int i = 1; i < n; i++) {
if (s[i] != s[0])
return false;
}
return true;
}
int main()
{
cin>>N;
cin >> t;
if (N == 1)
{
cout << "YES";
}
else if (allCharactersSame(t))
{
cout <<"YES";
}
else
{
cout<<"NO";
}
}
The problem with this is that it outputs YES no matter what, and we think it's because it takes the whitespace of the input into consideration. If we don't include spaces, it works fine. BUT the question dictates that we Have To have spaces separating our inputs. So, we're stumped. Any suggestions?
(I can't comment, therefore I write this as an answer.)
There is some other problem than you think, because the code in the question works as it should. When I gave it input "5 11111" it said "YES" when I gave it "5 12345" it said "NO".
Kai's first comment is slightly weird, when determining whether all characters in a string are the same it is sufficient to compare each of them to the first one, just as you do it in your allCharactersSame() method.
I'd suggest you add some checks on the provided input; the program should probably notice if given N doesn't match given strings' length and it should probably notice when the given string doesn't consist of numbers. As it is now, e.g. input "3 a" says "YES".

User Login Verification [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
The program is Working perfectly fine .. but in strings if i want to restrict my username to 8 characters what should i do ? ?
cout << "Enter your Username it should have a maximum limit of 8 characters\n " << endl;
getline(cin, user, '\n');
i want here that it should restrict user for 8 characters .. if greater then 8 .. then it should keep asking
user (while loop ??)) until user enters characters less then 8 ..
int mystrcmp(const char *s1, const char *s2)
{
while (*s1==*s2)
{
if(*s1=='\0')
return(0);
s1++;
s2++; }
return 1;//return(*s1-*s2);
}
your int mystrcmp(const char *s1, const char *s2) was returning the difference b/w the ascii values of first non-matched chars in strings s1 and s2 and it isnt always 1 as your code supposed to.
A clean implementation of your code can be found here ideone link
You have a few confusions, notably between C++ strings and C strings.
Your mystrcpy function is an attempt to copy a C style string, but it's not necessary in C++. Here's how you do it in C++. Replace this
mystrcpy(new_user,user)
with this
new_user = user;
As you can see it's a bit easier to copy a C++ string than a C string. You can delete the mystrcpy function.
Similarly your mystrcmp function is an attempt to compare C strings. Again it's not necessary in C++. Replace this
f = mystrcmp(user2,new_user);
if (f==0)
{
cout << "Successful Login!! \n ";
}
with this
if (user2 == new_user)
{
cout << "Successful Login!! \n ";
}
Again you can see that comparing C++ strings is easier than comparing C strings. Again you can delete the mystrcmp function.
There a few other errors, in the logic, and some missing semi-colons, but I'll leave you do figure those out.
Your code is pretty much all over the place. For instance:
You need to #include <string> if you're going to use std::string.
cin >> a; if ( a == 1 ) - what if the user doesn't enter an integer at all? You'll be comparing the value of an uninitialized int to 1, which puts you in undefined behavior land. You should check the return from cin, or at a minimum initialize a.
As John mentioned, you read in std::strings, and then attempt to treat them like C strings. Don't, just use new_user = user and if ( user2 == new_user ).
If the user doesn't "Enter 1 to enter Signup Screen" you take them to the signup screen anyway.
In your mystrcmp() function, you return 0 if *s1 == '\0', but you fail to check if *s2 == '\0'. This means two things - one, if s2 is shorter than s1, then you're going out of bounds and invoking undefined behavior again, and two, if s2 is longer than s1 but begins with s1 (e.g. if s1 contains "billy" and s2 contains "billybob") then your function will say they are equal when they are not.
Also in your mystrcmp() function, this: return(*s1-*s2) will either always return 0 less the value of the element of s2 with the same index as the last index of s1, or it'll invoke undefined behavior if s2 is shorter, as already explained. Either way, it's almost certainly not something you want to return.
mystrcpy(target,source) is not a valid function definition. This function also only copies the first character of source to the first character of target.
When you loop following an incorrect entry, you check if (f == 0) and if (f == 1), but you never set f during this loop, so no matter what the user enters, you'll always just be checking what the initial result was, regardless of what they enter next.

c++ string compare algorithm [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
what is your best string comparison algorithm?
i find O(n)
#include <string>
bool str_cpmr(char* str1, char* str2)
{
int l1 = strlen(str1), l2 = strlen(str2) ;
if(l1 != l2)
return false;
for(int i = 0 ; i < l1 ; i++)
if(str1[i] != str2[i])
return false ;
return true ;
}
and i wonder if there is any other / better solution.
also, how to test that accurately?
i propose to compare
100 matches
100 strings differing by one char swap
is there more to test string compare ?
how is it in stl c++ (slt string::compare) ?
thanks!!!!!
You function is O(n), but still takes roughly double the time necessary -- strlen walks through the string to find the length, then (assuming they're the same length) you walk through the strings again comparing the characters.
Instead of that, I'd walk through the strings until you reach a mismatch or the end of both strings. If you reach a mismatch, you return false. You return true if and only if you reach the end of both strings (simultaneously) without any mismatches first.
Logically it's hard to see how you can check all the values in a string for a single char mismatch in less than O(n) time - assuming you have no other info about the string.
If this is a real application and you have some knowledge of the strngs and the type of differences you could do better on average by checking every Nth char first if you know that it contains sequences of length 'N' eg part or phone numbers.
edit: Note this is still O(n), O() only describes the power of the scaling, it would just be O(n/N) which is still O(n). If you make the string 10x longer checking every Nth entry still takes 10x as long.
what is your best string comparison algorithm?
template< class T, class Alloc >
bool operator==( basic_string<T,Alloc>& lhs, basic_string<T,Alloc>& rhs );.
It compares two strings using only two characters of source code:
a==b;
Here's a non-smartalec answer, written in C:
bool str_cpmr(char* str1, char* str2)
{
while( *str1 && *str2 && *str1++ == *str2++ )
;
return *str1 == *str2;
}
It is exactly one loop, so it is obviously O(n), where n goes as length of the shorter string. Also, it is likely to compile to exactly 2n memory fetches. You can go faster with specialized string instructions (so calling strcmp() will probably go faster than this), but you probably won't go faster in straight C.
Your improved function might look like this:
bool str_cpmr(char* str1, char* str2)
{
if (NULL == str1 || NULL == str2) return false;
while (*str1 && *str2) {
if (*str1++ != *str2++) {
return false;
}
}
return *str1 || *str2 ? false : true;
}
If there is no additional information on the nature of the strings, there is nothing that can be better than O(n), where n is the length of the (shorter) string.
You cannot do with less than n comparisons! Give me an algorithm that can do it with n-1 comparisons. Then there must be a position in the string where the algorithm cannot tell if the characters are different or not. That way I can give you an example where you algorithm with n-1 comparisons fails.
You can only improve this by a constant factor. This will also take into account additional information, e.g. if you know that the underlying hardware compares 32-bit values faster than 8-bit values, then it will better to compare chunks of four characters instead of comparing character by character. You will not do much better.

How to remove a character from the string and change data if need it?

I have possible inputs 1M 2M .. 11M and 1Y (M and Y stand for months ) and I want to output "somestring1 somestring2.... and somestring12" note M and Y are removed and the last string is changed to 12
Example: input "11M" "hello" output: hello11
input "1Y" "hello" output: hello1
char * (const char * date, const char * somestr)
{
// just need to output final string no need to change the original string
cout<< finalStr<<endl;
}
The second string is getting output as a whole itself. So no change in its output.
The second string would be output as long as M or Y are encountered. As Stack Overflow discourages providing exact source codes, so I can give you some portion of it. There is a condition to be placed which is up to you to figure out.(The second answer gives that as well)
Code would be somewhat like this.
//Code for first string. Just for output.
for (auto i = 0 ; date[i] != '\0' ; ++i)
{
// A condition comes here.
cout << date[i] ;
}
And note that this is considering you just output the string. Otherwise you can create another string and add up the two or concatenate the existing ones.
is this homework? If not, here's what i'd suggest. (i ask about homework because you may have restrictions, not because we're not here to help)
1) do a find on 'M' in your string (using find), insert a '\0' at that position if one is found (btw i'm assuming you have well formatted input)
2) do a find on 'Y'. if one is found, insert a '\0' at that position. then do an atoi() or stringstream conversion on your string to convert to number. multiply by 12.
3) concatenate your string representation of part 1 or part 2 to your somestr
4) output.
This can probably be done in < 10 lines if i could be bothered.
the a.find('M') part and its checks can be conditional operator, then the conversion/concatenation in two or three lines at most.

C++ string manipulation / input

This is for homework! But I need help anyway. The assignment is to input a sentence then output the number of words, and the number of occurrences of each letter. The output must have the letters in alphabetical order. So far, I've been able to count the number of words and get all the letters to lower case so that I'll be able to keep count of them. My question is how to actually keep count of the letters.
Example of output:
I say Hi.
3 words
1 a
1 h
2 i
1 s
1 y
Here's the code that I have so far:
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
int letters[26];
char letter;
int word = 0;
cout << "Please enter a sentence: "<< endl;
do
{
cin.get(letter);
if(isspace(letter))
word++;
letter = tolower(letter);
cout << letter;
}
while (letter != '\n');
cout << "The number of words = " << word << endl;
return 0;
}
Should I input directly into a C-string? or will that mess up the word count?
If you're allowed to use STL, use std::map for mapping letters to counters. It will additionally sort the letters.
Otherwise, treat chars as indexes in an array of counters and increment them.
My question is how to actually keep
count of the letters
It's fairly straight forward. Simply create an array of 26 integers, (one for each letter), and initialize it to zero.
int letters[26] = { 0 }; // Initialize array to zero
Each value in the array corresponds to a count of a particular letter. Array index 0 refers to 'a', array index 1 refers to 'b', and so on. Then, everytime you encounter a letter, increment the appropriate value in the array. You can use the character 'a' (ASCII value 97) as a starting offset. So, given the variable char letter; you would do:
++letters[tolower(letter) - 'a'];
But always make sure that before you increment the appropriate value in the array, you check that isalpha(letter) && islower(letter) to make sure that your letter is in the range of lowercase a-z; otherwise you will access an index beyond the bounds of the array. You can also test for this condition by saying if (letter >= 'a' && letter <= 'z').
Hint: tolower(letter)-'a' is:
0 if letter is a
1 if letter is b
...
Hm, just few points to make your home task more useful to you (and your code more correct):
Think what happens if you have file with several spaces in a row (word counting).
Think how to be more correct with 'letters' (check for isalpha() at least). Also isalpha() could be key for simpler counting with fixed array [256] (this might be even the best solution as for performance vs std::map usage, check std::map documentation anyway).
Think about more effective file input. At least line at once.