Determine if two strings are anagram? - c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static int comp(const void *a, const void *b);
int main(int argc, char ** argv)
{
char s1[]="";
char s2[]="";
char *fmt = "%[^\n]%*c";
printf("Enter the first word? ");
scanf(fmt,&s1);
printf("Enter the second word? ");
scanf(fmt,&s2);
qsort(s1, strlen(s1), 1, comp);
qsort(s2, strlen(s2), 1, comp);
printf("%s : %s - %s\n", s1, s2, strcmp(s1, s2) ? "No" : "Yes");
return 0;
}
static int comp(const void *a, const void *b)
{
const char *pa = (char*)a;
const char *pb = (char*)b;
return
(*pa > *pb) ? 1 :
(*pa < *pb) ? -1 :
0;
}
When I key in 'smartest' as my first string and 'mattress' as my second string , my output becomes
emrsstt : aemrsstt - No
Why is the first character of the string missing?
Been sitting on this for hours. Gladly appreciate if someone could point out the silly mistake I may have made.

A smart way of doing this is to first check for a probable anagram. You do this by
Comparing the string lengths.
XORing every char from the total set; drawn from both strings.
If the result of (2) is not zero then the strings cannot possibly be anagrams. The advantage of doing this is that (2) is extremely fast in c and most strings are not anagrams, even if they are the same length. If your feeling particularly ambitious, you could combine (1) and (2) into a single O(N) algorithm!
Once you've done that, call your main code body. Your problem is in not allowing for the null terminator on each string. Your need to allocate enough space for the string characters plus one extra element for the null terminator.

Basically when you have to check whether any 2 set of values are same or not XOR operation is helpful.
Input Output
A B
0 0 0
0 1 1
1 0 1
1 1 0
So using this we can solve your problem as done below:
#include <stdio.h>
#include<stdlib.h>
#include <string.h>
int main()
{
int i=0,j=0,f;
char a[30] = "gooo";
char b[30] = "ooog";
if(strlen(a) == strlen(b))
{
while(a[i] != '\0')
{
j = 0;
f =0;
while(b[j] != '\0')
{
if( !(a[i] ^ b[j]) )
{
f =1;
break;
}
j++;
}
if(f)
i++;
else
break;
}
printf("%d\n",i);
if(i == strlen(a))
printf("Yes\n");
else
printf("No\n");
}
return 0;
}

Please check and the below solution for the anagram problem. This solution checks if two strings have identical counts for each unique char
bool anagram (char s[], char t[])
{
if (strlen(s) != strlen(t)){
return false;
}
int letters[256];
memset(letters,(int)0,sizeof(letters));
int numUniqueChars = 0;
int numCompletedT = 0;
int i;
for (i=0; i < strlen(s); i++){
if (letters[(int)s[i]]==0){
++numUniqueChars;
}
letters[s[i]]=letters[s[i]]+1;
}
for (i=0; i < strlen(t); i++){
int c = (int)t[i];
if (letters[c] == 0){
return false;
}
letters[c]=letters[c]-1;
if (letters[c] == 0){
numCompletedT++;
if (numUniqueChars==numCompletedT){
return i == strlen(t)-1;
}
}
}
return false;
}

Related

I am trying to make a function that checks whether all characters in a string are unique, and returns 0 if this is so, or 1 if not all are unique

I'm not sure what is wrong with my code. It just seems to print 0 most of the time, when I change string word. Would appreciate any help/comments - is it a problem with the logic in my code? If so, where, and how can I rectify it?
#include <stdio.h>
#include <cs50.h>
#include <string.h>
int check_unique_letters(string words);
int main (void)
{
string word = "ABCB" ;
printf ("%i\n", check_unique_letters (word));
}
int check_unique_letters (string words)
{
int j = 0;
do
{ int x = (int) (words [j]) ;
int y = 0;
for (int i=j + 1; i<strlen(words); i++)
{
if ((int)words[i] == x)
{
y += 1;
}
else
{
y+= 0;
}
}
if (y>0)
{
return 1;
break;
}
else
{
j = j+1;
}
}
while (j < strlen (words));
}
The function returns nothing outside the do-while loop though its return type is not void.
That is after the do-while loop you need to place the statement
return 0;
Pay attention to that there is no need to use objects of the type int like
int x = (int) (words [j]) ;
and there is a redundant code that does not have an effect like this else
else
{
y+= 0;
}
or like the break statement
if (y>0)
{
return 1;
break;
}
And it would be more logically consistent if the function returned non-zero in case when all symbols are unique.
Also calling the function strlen is inefficient.
I would write the function the following way
#include <stdio.h>
#include <string.h>
int check_unique_letters( const char *s )
{
if (*s)
{
while (s[1] != '\0' && strchr( s + 1, *s ) == NULL) ++s;
}
return *s == '\0' || s[1] == '\0';
}
int main( void )
{
const char *s = "ABCB";
printf( "All characters of the string \"%s\" are %s.\n",
s, check_unique_letters( s ) ? "unique" : "not unique" );
s = "ABCD";
printf( "All characters of the string \"%s\" are %s.\n",
s, check_unique_letters( s ) ? "unique" : "not unique" );
}
The program output is
All characters of the string "ABCB" are not unique.
All characters of the string "ABCD" are unique.
Here is a quick implementation of what you need. You can quickly compare as to where you might be going wrong.
Feel free to modify the program to suit your needs.
You can see it running here.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int check_unique_chars(char* str, int length)
{
// standard null checks
if (length == 0 || str == NULL)
return 1;
// The easiest way to do this is to, for each character
// compare every other character ahead of it. If there is a match, then return 1. Else return 0.
for(int idx =0; idx < length; ++idx)
{
for(int idx1 =idx+1; idx1 < length; ++idx1)
{
if (str[idx] == str[idx1])
return 1;
}
}
return 0;
}
int main(void)
{
char* s = "Hel0";
char* s1 = "banana";
printf("string has unique chars: %s\n", check_unique_chars(s, strlen(s)) == 0 ? "true" : "false");
printf("string has unique chars: %s\n", check_unique_chars(s1, strlen(s1)) == 0 ? "true" : "false");
return EXIT_SUCCESS;
}
I am reasonably sure this is not the most efficient implementation, but it is quite obvious in its operation and you should be able to modify it to suit your needs.

My string assigning correctly into my char array (C)

#include <stdio.h>
#include <string.h>
void mirror(char c[])
{
int l = strlen(c);
char s;
for (int i = 0; i < l/2;i++)
{
s = c[i];
c[i] = c[l-i-1];
c[l-i-1] = s;
}
}
void decimal_to_binary(unsigned int n,char binary_res[]){
char r = n%2;
unsigned int q = (n - r)/2;
int i = 0;
while (q != 0)
{
i++;
r = n%2;
q = (n - r)/2;
n = q;
printf("%d\n",q);
binary_res[i] = r+'0';
}
mirror(binary_res);
}
int main(){
int n = 34; char res[10];
printf("%d\n",n);
decimal_to_binary(n,res);
printf("%s\n",res);
return 0;
}
I wrote this code which is really simple and I wanted it to convert a decimal to a binary through some repeated divisions. But there is a problem I don't understand because if I remove the +'0' when I assign the rest to the ith value in the result array, it displays nothing when I call it printf but when I add the +'0' it adds some weird characters. But I think i cmes from the fact that it is not ascii encording but UTF-8 so 0 hasn't a value of 0 but of 48. But the 0 value is for a null string so '' but when I add it to the r with +'' it shows nothing !
I don't understand what I am doing wrong here but I think there is multiple things I do wrong.
Thanks in advance !
I see three bugs:
You use i++ too soon. You place the first bit at binary_res[1] when it should be placed at binary_res[0].
You don't add a terminating NUL to binary_res.
You don't modify the binary_res at all when the n parameter is zero.
I check this statement '(n%2)' with loop statement and I fill the array, then I use procedure mirror to reverse the string like this:
#include <stdio.h>
#include <string.h>
void mirror(char c[],int l);
void decimal_to_binary(unsigned int n,char binary_res[]);
int main()
{
int n = 40; char res[10];
printf("%d\n",n);
decimal_to_binary(n,res);
printf("The binary form of number %d is %s\n",n,res);
return 0;
}
void mirror(char c[],int l)
{
char s;
for (int i = 0; i < l/2;i++)
{
s = c[i];
c[i] = c[l-i-1];
c[l-i-1] = s;
}
}
void decimal_to_binary(unsigned int n,char binary_res[])
{
int i = 0;
while (n != 0)
{
switch(n%2)
{
case 1:
{
binary_res[i]='1';
i++;
}break;
case 0:
{
binary_res[i]='0';
i++;
}break;
}
n = n/2;
}
binary_res[i]='\0';
mirror(binary_res,i);
}

How to compare an array to a reversed one and check if their values match?

I wrote a program that reverses an array with the strrev() function and checks if its values matches the original one, sort of a palindrome. When the values match, it prints Palindrome, else, Not a palindrome.
But when I compare them, and the values don't match, it still prints Palindrome.
Here is the code:
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <string.h>
#define MAX_LEN 100
void palindrom(char string[]);
int main()
{
char string[MAX_LEN] = { 0 };
printf("Enter string (max length 100 chars): ");
fgets(string, MAX_LEN, stdin);
if(string[strlen(string)-1] == '\n') { string[strlen(string)-1] = 0; }
palindrom(string);
return (0);
}
void palindrom(char string[])
{
int check = 0;
check = strcmp(strrev(string), string);
if (check == 0)
{
printf("Palindrome");
}
else
{
printf("Not a palindrome");
}
}
What's my problem? Thanks.
From what I can tell strrev may modify the original string as well, so you need to copy it.
The key is strrev.
Here's a program in C that will do what you're testing for:
#include <stdio.h>
#include <string.h>
int main()
{
char a[100], b[100];
printf("Enter the string to check if it is a palindrome\n");
fgets(a, 100, stdin);
strcpy(b,a);
strrev(b);
if (strcmp(a,b) == 0)
printf("Entered string is a palindrome.\n");
else
printf("Entered string is not a palindrome.\n");
return 0;
}
Since others have clarified what the problem is, I would like to point that it would be faster to check if s[0] == s[len-1], s[1] == s[len-2], until half (rounded up) of the string has been checked.
This would require no extra memory, no copy and half as many comparisons.
Something along the lines of:
void palindrom(char string[])
{
int len = strlen(string) - 1;
int i, limit = len/2 + (len % 2);
for (i = 0; i < limit; i++){
if (string[i] != string[len-i]){
printf("Not a palindrome\n");
return;
}
}
printf("Palindrome\n");
}
Your function fails because strrev modifies the string. You effectively always compare the reversed string to itself.
Here is an alternate function that does not modify the string:
void palindrom(const char *str) {
for (size_t i = 0, j = strlen(str); i < j; i++, j--) {
if (str[i] != str[j - 1]) {
printf("Not a palindrome\n");
return;
}
}
printf("Palindrome\n");
}
You don't need to use strrev to test for a palindrome the following function detects a palindrome just fine without using non-standard C functions:
int ispalindrome(char *str, int len)
{
char *p = &str[0];
char *q = &str[len - 1];
do
{
if(p >= q)
{
return 1;
}
} while (*p++ == *q--);
return 0;
}

Specified letter count with recursion

I'm trying to write a recursive algorithm that obtains to count specified a letter by user. But, I'm stuck in two cases. First, I think I must get 2 as result, I can't. Second, If there is no limit key, for instance the limit character specified as z by user , how the characters can be scanned up to end character here g ? The problem little bit complicated for me. I need your advices and ideas. Thank you all appreciated answers.
example string is: how are you i am testing
another examples:
#include <stdio.h>
int lettercount(char* str, char key, char limit);
int main(){
char test[]="how are you i am testing";
int num;
num=lettercount(test,'a','t');
printf("%d",num);
return 0;
}
int lettercount(char* str, char key, char limit)
{
int count = 0;
if(str[0] == limit)
{
return 0;
}
else if(str[0] == key)
{
lettercount(&str[1], key, limit);
count++;
}
else
lettercount(&str[1], key, limit);
return count;
}
as the code is unwinding from the recursion(s)
it needs to accumulate the count
the following code should work for your needs.
Note: this returns 0 if key and limit are the same char
int lettercount(char* str, char key, char limit)
{
int count = 0;
if(str[0] == limit)
{
return 0;
}
// implied else, more char in string to check
if(str[0] == key)
{
count++;
}
count += lettercount(&str[1], key, limit);
return count;
} // end function: lettercount
With a recursive function, you need 3 things. (1) set up in the function that prepares for the next call; (2) a recursive call; and (3) a way to terminate the recursion. Here is one approach. Note: the version in the code below is a long version for readability, a short version is included at the end:
#include <stdio.h>
/* recursively find the number of occurrences
of 'c' in 's' (n is provided as '0')
*/
int countchar (char *s, char c, int n)
{
char *p = s;
if (!*p)
return n;
if (*p == c)
n = countchar (p+1, c, n+1);
else
n = countchar (p+1, c, n);
return n;
}
int main (int argc, char **argv) {
if (argc < 3) {
fprintf (stderr, "\n error: insufficient input. Usage: %s <string> <char>\n\n", argv[0]);
return 1;
}
int count = countchar (argv[1], *argv[2], 0);
printf ("\n There are '%d' '%c's in: %s\n\n", count, *argv[2], argv[1]);
return 0;
}
output:
$ ./bin/rec_c_in_s "strings of s'es for summing" s
There are '5' 's's in: strings of s'es for summing
You can make the function shorter, but slightly less readable with:
int countchar (char *s, char c, int n)
{
char *p = s;
if (!*p) return n;
return countchar (p+1, c, (*p == c) ? n+1 : n);
}

find the count of substring in string

I have to find the count of a substring in a string using the C language.
I'm using the function strstr but it only finds the first occurrence.
My idea of the algorithm is something like searching in the string while strstr does not return null and
to substring the main string on each loop.
My question is how to do that?
You could do something like
int countString(const char *haystack, const char *needle){
int count = 0;
const char *tmp = haystack;
while(tmp = strstr(tmp, needle))
{
count++;
tmp++;
}
return count;
}
That is, when you get a result, start searching again at the next position of the string.
strstr() doesn't only work starting from the beginning of a string but from any position.
Should already processed parts of the string should be consumed or not?
For example, what's the expect answer for case of searching oo in foooo, 2 or 3?
If the latter (we allow substring overlapping, and the answer is three), then Joachim Isaksson suggested the right code.
If we search for distinct substrings (the answer should be two), then see the code below (and online example here):
char *str = "This is a simple string";
char *what = "is";
int what_len = strlen(what);
int count = 0;
char *where = str;
if (what_len)
while ((where = strstr(where, what))) {
where += what_len;
count++;
}
USE KMP and you can do it in O(n)
int fail[LEN+1];
char s[LEN];
void getfail()
{
//f[i+1]= max({j|s[i-j+1,i]=s[0,j-1],j!=i+1})
//the correctness can be proved by induction
for(int i=0,j=fail[0]=-1;s[i];i++)
{
while(j>=0&&s[j]!=s[i]) j=fail[j];
fail[i+1]=++j;
if (s[i+1]==s[fail[i+1]]) fail[i+1]=fail[fail[i+1]];//optimizing fail[]
}
}
int kmp(char *t)// String s is pattern and String t is text!
{
int cnt=0;
for(int i=0,j=0;t.s[i];i++)
{
while(j>=0&&t.s[i]!=s[j]) j=fail[j];
if (!s[++j])
{
j=fail[j];
cnt++;
}
}
return cnt;// how many times s appeared in t.
}
The results can be different depending whether you allow an overlap or not:
// gcc -std=c99
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
static int
count_substr(const char *str, const char* substr, bool overlap) {
if (strlen(substr) == 0) return -1; // forbid empty substr
int count = 0;
int increment = overlap ? 1 : strlen(substr);
for (char* s = (char*)str; (s = strstr(s, substr)); s += increment)
++count;
return count;
}
int main() {
char *substrs[] = {"a", "aa", "aaa", "b", "", NULL };
for (char** s = substrs; *s != NULL; ++s)
printf("'%s' -> %d, no overlap: %d\n", *s, count_substr("aaaaa", *s, true),
count_substr("aaaaa", *s, false));
}
Output
'a' -> 5, no overlap: 5
'aa' -> 4, no overlap: 2
'aaa' -> 3, no overlap: 1
'b' -> 0, no overlap: 0
'' -> -1, no overlap: -1
Assuming s and substr are non-null and non-empty:
/* #times substr appears in s, no overlaps */
int nappear(const char *s, const char *substr)
{
int n = 0;
const char *p = s;
size_t lenSubstr = strlen(substr);
while (*p) {
if (memcmp(p, substr, lenSubstr) == 0) {
++n;
p += lenSubstr;
} else
++p;
}
return n;
}
/*
* C Program To Count the Occurence of a Substring in String
*/
#include <stdio.h>
#include <string.h>
char str[100], sub[100];
int count = 0, count1 = 0;
void main()
{
int i, j, l, l1, l2;
printf("\nEnter a string : ");
scanf("%[^\n]s", str);
l1 = strlen(str);
printf("\nEnter a substring : ");
scanf(" %[^\n]s", sub);
l2 = strlen(sub);
for (i = 0; i < l1;)
{
j = 0;
count = 0;
while ((str[i] == sub[j]))
{
count++;
i++;
j++;
}
if (count == l2)
{
count1++;
count = 0;
}
else
i++;
}
printf("%s occurs %d times in %s", sub, count1, str);
}

Resources