using strcmp between string array and 2d array string - c++

I need to search a word in 2d array an array that I enter but when Im using strcmp function, I have an error "No Matching function for call to 'strcmp'
bool checkIfSameMedicine (char str1[], char str2[][MAXSIZE])
{
for (int i = 0; i <= 3; i++)
{
if (strcmp(str2, str1))
{
return true;
}
return false;
}
}

You have to write at least
for (int i = 0; i <= 3; i++)
{
if (strcmp(str2[i], str1) == 0)
{
return true;
}
}
return false;
Though the code looks not good due to using the magic number 3.
The function should be declared and defined like
bool checkIfSameMedicine( const char str2[][MAXSIZE]), size_t n, const char str1[] )
{
size_t i = 0;
while ( i != n && strcmp( str2[i], str1 ) != 0 ) ++i;
return n != 0 && i != n;
}

Related

is there any faster way to do this exercise?

int function2 (const char * string1) returning the number of unique digits appearing in the string, e.g. function2 ("ab512af6kc1") -> 3.
int function2(const char* string1) {
int zero = 0, one = 0, two = 0, three = 0, four = 0, five = 0, six = 0,
seven = 0, eight = 0, nine = 0, counter = 0;
for (int i = 0; i < strlen(string1); i++) {
if (string1[i] == '0') {
zero++;
}
if (string1[i] == '1') {
one++;
}
if (string1[i] == '2') {
two++;
}
if (string1[i] == '3') {
three++;
}
if (string1[i] == '4') {
four++;
}
if (string1[i] == '5') {
five++;
}
if (string1[i] == '6') {
six++;
}
if (string1[i] == '7') {
seven++;
}
if (string1[i] == '8') {
eight++;
}
if (string1[i] == '9') {
nine++;
}
}
if (zero == 1) {
counter++;
}
if (one == 1) {
counter++;
}
if (two == 1) {
counter++;
}
if (three == 1) {
counter++;
}
if (four == 1) {
counter++;
}
if (five == 1) {
counter++;
}
if (six == 1) {
counter++;
}
if (seven == 1) {
counter++;
}
if (eight == 1) {
counter++;
}
if (nine == 1) {
counter++;
}
return counter;
}
It's every correct in this code, but it's long a bit. Could someone help me and write SHORTER code? It's the only way that I can measure up to this exercise.
You can use an array instead of 10 variables. Calculate the index in the array by converting the character to an integer.
int function2(const char *in) {
// Array to hold digits occurence counts.
unsigned digits[10]{};
// Iterate over the characters in input.
// Better (auto i : std::string_view(in)) in C++17.
for (auto i = in; *i; ++i) {
if (isdigit(*i)) {
// Increment the proper digit index.
digits[*i - '0']++;
}
}
int count = 0;
// Go through digit occurences.
for (auto i : digits) {
// If the digit occurred only once.
if (i == 1) {
// Increment the count.
count++;
}
}
return count;
}
To shorten your code, use an array instead of 10 individual variables:
int digits[10] = {0}; // instead of int zero = 0, one = 0, ...
To check whether a char is a representation of a digit, use isdigit:
if (isdigit(string1[i])) // instead of if (string1[i] == '0'), if (string1[i] == '1'), ...
The only non-trivial part is to convert a char to the corresponding int:
string1[i] - '0'
This code subtracts the character code of 0 (usually 48) from the character code of a digit (usually 49 for 1, 50 for 2, ..., 57 for 9). The result is an index to your array of counters.
So, to increase the proper array element, use the following code:
digit = string1[i] - '0';
digits[digit]++; // instead of zero++, one++, ...
After the code goes over the input string, count the number of digits which appeared once:
int counter = 0;
for (digit = 0; digit < 10; ++digit)
{
if (digits[digit] == 1)
++counter;
}
Use a hash table collection class to keep track of unique digits. In this case, unordered_set will do just fine. Don't even bother converting the char to integer. You're just looking for unique chars between '0' and '9'.
#include <string>
#include <unordered_set>
size_t getUniqueDigits(const std::string& string1)
{
std::unordered_set<char> table;
for (char c : string1)
{
if ((c >= '0') && (c <= '9'))
{
table.insert(c);
}
}
return table.size();
}
A more traditional "C" based solution that doesn't use any std:: collections or objects is to use an array to be that "set"
int getUniqueDigits(const char* string1)
{
int table[10] = {0};
int count = 0;
const size_t len = (string1 != nullptr) ? strlen(string1) : 0;
for(size_t i = 0; i < len; i++)
{
char c = string1[i];
if ((c >= '0') && (c <= '9'))
{
table[c - '0'] = 1;
}
}
for (char j = '0'; j <= '9'; j++)
{
count += table[j];
}
return count;
}
Just use an ordinary array as for example in this demonstrative program
#include <iostream>
size_t unique_digits( const char *s )
{
unsigned char digits[10] = { 0 };
for ( ; *s; ++s )
{
if ( '0' <= *s && *s <= '9' )
{
if ( digits[*s - '0'] != 2 ) ++digits[*s - '0'];
}
}
size_t count = 0;
for ( unsigned char c : digits ) count += c == 1;
return count;
}
int main()
{
std::cout << unique_digits( "ab512af6kc1" ) << '\n';
return 0;
}
The program output is
3
Or you can declare the array of the element type size_t. In this case the function will look the following way
#include <iostream>
size_t unique_digits( const char *s )
{
size_t digits[10] = { 0 };
for ( ; *s; ++s )
{
if ( '0' <= *s && *s <= '9' )
{
++digits[*s - '0'];
}
}
size_t count = 0;
for ( unsigned char c : digits ) count += c == 1;
return count;
}
int main()
{
std::cout << unique_digits( "ab512af6kc1" ) << '\n';
return 0;
}
I think you already have many good solutions.
Here is mine version anyway
int function2(const char* string1) {
int count[10] = {0};
int counter = 0;
int i;
for(i = 0; i < strlen(string1); i++)
int a = (++count[string1[i]-'0']);
if(a == 1)counter++;
if(a == 2)counter--;
return counter;
}
I haven't tried it. Hope there is no error
Edit:
I tried it. It seems to work fine now.

Leetcode 28 - Implement strStr(): question

I am experiencing a bug in my submissions for Leetcode 28 that has thus far eluded me. My code works for most test cases but I am getting hung up on scenarios such as haystack = "mississippi", needle = "issip".
I have tried debugging and found that the entire haystack string is iterated through and it is returning -1 or not found. The substring length it is finding at each occurrence of 'i' is 4, 1, 1.
int strStr(string haystack, string needle) {
if (needle.empty()) {
return 0;
}
if (haystack.empty() && !needle.empty()) {
return -1;
}
int i = 0, j = 0, ans = 0;
for (i; i < haystack.length(); i++) {
if (haystack[i] == needle[0]) {
j = 0;
ans = i;
for (j; j < needle.length(); j++) {
/*
if (haystack[i++] == needle[j]) {
continue;
}
else {
break;
}
*/
if (haystack[i++] != needle[j]) {
break;
}
}
if (j == needle.length()) {
return ans;
}
}
if (j == needle.length()) {
return ans;
}
}
return -1;
}
Input: "mississippi", "issip"
Output: -1 (ans = 10, j = 1)
The function has several drawbacks.
For starters it should be declared like
std::string::size_type strStr( const std::string &haystack, const std::string &needle );
and if the second string is not found in the first string the function should return std::string::npos as all similar member functions of the class std::string do.
The function parameters shell be of constant referenced types.
The condition in this if-statement
if (haystack.empty() && !needle.empty())
has a redundant operand. It could be rewritten like
if (haystack.empty())
This loop
for (i; i < haystack.length(); i++)
should stop its iterations when the size of the tail of the first string is less than the size of the second string.
in this if-statement
if (haystack[i++] != needle[j]) {
the variable i is incremented that results in incrementing the variable two times: one in this statement and the second time in the loop.
The second pair of these statements
if (j == needle.length()) {
return ans;
is redundant.
The function can be written the following way as it is shown in the demonstrative program.
#include <iostream>
#include <string>
std::string::size_type strStr( const std::string &haystack, const std::string &needle )
{
if ( needle.empty() )
{
return 0;
}
else if ( haystack.empty() )
{
return -std::string::npos;
}
else
{
std::string::size_type ans = std::string::npos;
auto n1 = haystack.length();
auto n2 = needle.length();
for ( std::string::size_type i = 0; ans == std::string::npos && i + n2 <= n1; i++ )
{
std::string::size_type j = 0;
while ( j < n2 && haystack[i+j] == needle[j] ) j++;
if ( j == n2 ) ans = i;
}
return ans;
}
}
int main()
{
std::string haystack( "mississippi" );
std::string needle( "issip" );
std::cout << strStr( haystack, needle ) << '\n';
return 0;
}
Its output is
4
The problem is that you modify i in
if (haystack[i++] != needle[j]) {
Thus preventing a second potential match from being explored. Try
if (haystack[i + j] != needle[j]) {
and fix any knock-on issues. I expect it to work as-is, though.

Sorting a vector of strings by the first letter in non-ascii order in C++

I have a text file with a list of words.
I used ifstream to read these words into a vector and now I am trying to sort them in an order similar to:
A a B b C c [...]
I tried to implement this using a third for loop inside of a bubble search algorithm to look at the first character of each word (I know this is far from the most efficient way especially if I was using a large data set)
And then check whether the letter and the next letter were uppercase or lowercase and switching if the uppercase letter was the same letter as the current letter, but this didn't seem to work.
void bubble_Sort (vector <string> & words)
{
for (unsigned i = words.size(); i >= 2; --i)
{
for (unsigned k = 0; k + 1 < i; k++)
{
int hi = k+1;
string temp1 = words[hi];
string temp2 = words[k];
int smallsize = words[hi].size();
int smallprecedence = 0;
if (words[k].size() < words[hi].size())
smallsize = words[k].size();
for (unsigned j = 0; j < smallsize; j++)
{
if (temp1[j] >= 'A' && temp1[j] <= 'Z')
{
if (temp2[j] >='a' && temp2[j] <= 'z')
{
char lowercase1 = temp1[j] + 32;
if (lowercase1 == temp2[j])
{
string temp = words[k];
words[k] = words[hi];
words[hi] = temp;
break;
}
}
else if (temp2[j] >= 'A' && temp2[j] <= 'Z')
{
if (temp1[j] < temp2[j])
{
string temp = words[k];
words[k] = words[hi];
words[hi] = temp;
break;
}
}
}
if (temp1[j] >= 'a' && temp1[j] <= 'z')
{
if (temp2[j] >= 'A' && temp2[j] <= 'Z')
{
char uppercase1 = temp1[j] - 32;
if (uppercase1 < temp2[j])
{
string temp = words[k];
words[k] = words[hi];
words[hi] = temp;
break;
}
}
else if (temp2[j] >= 'a' && temp2[j] <= 'z')
{
if (temp1[j] < temp2[j])
{
string temp = words[k];
words[k] = words[hi];
words[hi] = temp;
break;
}
}
}
else if (temp1[j] == temp2[j] && temp1.size() < temp2.size())
++smallprecedence;
}
if (smallprecedence == smallsize)
{
string temporary = words[k];
words[k] = words[hi];
words[hi] = temporary;
}
}
}
}
Don't reinvent the wheel. Just modify the default comparison function so aA < bB (regardless of case) and A < a.
EDIT I used the wrong comparison function. It should return true for <, and false for >=. This has been fixed
std::vector<std::string> vec;
//
std::sort(vec.begin(), vec.end(), [](const std::string& lhs, const std::string& rhs)
{
const char* s1=lhs.c_str();
const char* s2=rhs.c_str();
while(true) {
// first ignore case
if ( std::toupper(*s1) < std::toupper(*s2) ) return true;
if ( std::toupper(*s1) > std::toupper(*s2) ) return false;
// end of both strings, exact match
if ( *s1 == 0 && *s2 == 0 ) return false;
// compare upper case vs lower case ('A' vs 'a')
if ( *s1 > *s2) return false;
if ( *s1 < *s2) return true;
++s1; ++s2;
}
});
First, get rid of the hard-coded ASCII-isms. C and C++ have long had functions for determining whether a character is a letter, a digit, uppercase, lowercase, etc. Look them up.
Second, describe clearly what goes into determining the order that you want the result to be in.
Third, from that description, write a function that takes two strings, and tells you whether the first string should come before the second. Use that function in the sort.
You can sort a vector using std::sort and get a reference to the first character in a std::string using std::string::at() :
std::vector<std::string> vec;
//
std::sort(vec.begin(), vec.end(), [](const std::string& lhs, const std::string& rhs)
{
char l_ch, r_ch;
l_ch = lhs.at(0);
r_ch = rhs.at(0);
return l_ch < r_ch;
});
I think it's really enough to skip exactly equal prefixes and then compare once with uppercasing:
std::vector<std::string> vec;
//
std::sort(vec.begin(), vec.end(), [](const std::string& lhs, const std::string& rhs)
{
const char* s1=lhs.c_str();
const char* s2=rhs.c_str();
while(*s1 && *s1 == *s2) {++s1; ++s2;}
int rc = toupper(*s1) - toupper(*s2);
if (rc) return rc;
return *s1 - *s2;
});
If you need to compare by first letter only, simply remove while(*s1 && *s1 == *s2) {++s1; ++s2;}

count the ocurrences of substrings

I've a task to count the occurrences of sub string in a char String. I write this code but on certain inputs output is wrong. like string is "hassana" and sub is "as" then it outputs 2 ...some one plz help me
int CharString :: countOccurenceOf(const char* substr)
{
int count = 0;
bool find = false;
for(int i = 0; i < size1; i++)
{
if(cstr[i] == substr[0])
{
int x = i;
int c = 1;
find = true;
while ( substr[c] != '\0' && find == true && (x+1) < size1)
{
if(cstr [x+1] != substr[c])
{
find = false;
}
c++;
x++;
}
if (find == true)
{
count++;
i = i + c-1;
}
}
}
return count;
}
Got some Solution.....is that okay?
int CharString :: countOccurenceOf(const char* substr)
{
int len = 0;
if ( substr != '\0')
{
while( substr[len] != '\0')
len++;
}
int count = 0;
bool find = false;
for(int i = 0; i < size1; i++)
{
if(cstr[i] == substr[0])
{
int x = i;
int c = 1;
find = true;
while ( substr[c] != '\0' && find == true && (x+1) < size1)
{
if(cstr [x+1] != substr[c])
{
find = false;
}
c++;
x++;
}
if (find == true && c == len)
{
count++;
i = i + c-1;
}
}
}
return count;
}
The problem is that you're breaking automatically if x+1 < size1. If the first character of the substring matches the last character of the main string, then this will automatically break and "find" will still be set to true so you'll increment matches by 1. There are numerous ways to change your code to fix this problem; hopefully you can find one now that you know what the problem is.
Assuming cstr is your class internal string:
int CharString :: countOccurenceOf(const char* substr)
{
int occurrencies = 0;
unsigned char* s = cstr;
while (s) {
if (strstr(s,substr)) { occurrencies++; s+= strlen(substr); }
else s++;
}
return occurrencies;
}

how to check whether 2 strings are rotations to each other ?

Given 2 strings, design a function that can check whether they are rotations to each other without making any changes on them ? The return value is boolean.
e.g ABCD, ABDC, they are not rotations. return false
ABCD, CDAB or DABC are rotations. return true.
My solution:
shift one of them to right or left one position and then compare them at each iteration.
If they are not equal at all iterations, return false. Otherwise, return true.
It is O(n). Are there other more efficient solutions ?
What if the contents of them cannot be changed ?
thanks
Concatenate the given string with the given string.
Search for the target string in the concatenated string.
Example:
Given = CDAB
After step 1, Concatenated = CDABCDAB
After step 2, Success CDABCDAB
^^^^
Rather than shifting one of them, it might be more efficient to use two index variables. Start one at 0 each time and the other at each of the possible positions (0 to N-1) and increment it mod N.
If you can't modify the strings, just take the first character of string1 and compare it to each character of string2. When you get a match, compare the second char of string1 to the next char of string2, and so on.
Pseudocode:
len = strlen(string1);
len2 = strlen(string2);
if( len != len2 )
printf("Nope.");
for( int i2=0; i2 < len; i2++ ) {
for( int i1=0; i1<len; i1++ ) {
if( string1[i1] != string2[(i2+i1)%len] )
break;
}
if( i1 == len ) {
print("Yup.");
break;
}
}
A simple one would be:
(s1+s1).find(s2) != string::npos && s1.size() == s2.size();
#include <iostream>
#include <cstring>
#include<string>
using namespace std;
void CompareString(string, string, int);
int ComputeStringLength(string str);
int main()
{
string str = ""; string str1 = ""; int len = 0, len1 = 0;
cout << "\nenter string ";
cin >> str;
cout << "\nenter string 2 to compare:- ";
cin >> str1;
len = ComputeStringLength(str);
len1 = ComputeStringLength(str1);
if (len == len1)
CompareString(str, str1, len);
else
cout << "rotation not possible";
getchar();
return 0;
}
int ComputeStringLength(string str)
{
int len = 0;
for (int i = 0; str[i] != '\0'; i++)
{
len++;
}
return len;
}
void CompareString(string str, string str1, int n)
{
int index = 0, flag = 0, curr_index = 0, count1 = 0, flagj = 0;
for (int i = 0; i<n; i++)
{
for (int j = flagj; j<n; j++)
{
if (str[i] == str1[j])
{
index = j;
flagj =j;
count1++;
flag++;
if (flag == 1)
{
curr_index = index;
}
break;
}
}
}
int temp = count1;
if (count1 != n)
{
if (curr_index>=0)
{
int k = 0;
for (int i = n - 1; i>n - curr_index - 1; i--)
{
if (str[i] == str1[k])
{
temp++;
k++;
}
}
}
if (temp == n)
{
cout << "\n\nstring is same after rotation";
}
else
{
cout << "\n\nstring is not same after rotation";
}
}
else
{
cout << "\n\nstring is same after rotation";
}
}
https://dsconceptuals.blogspot.in/2016/10/a-program-to-check-if-strings-are.html