Comparing the permutations of two strings in C [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 4 years ago.
Improve this question
I've just started out with learning C-basics and tried solving this problem where, we have to check if two strings are equal provided any permutation.
You may refer to this link: https://www.hackerearth.com/practice/basic-programming/input-output/basics-of-input-output/practice-problems/algorithm/two-strings-4/
I just wanted to get some solutions on how can I improve my code which gives the output as only 'NO':
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
int i, j, k, m, n, o, p;
char a[100000], b[100000], *c, *d;
scanf("%d", &i);
for (j = 0; j < i; j++)
{
scanf("%s %s", a, b);
}
for (k = 0; a[k] != '\0'; k++)
{
n = rand() % k;
}
for (m = 0; b[m] != '\0'; m++)
{
o = rand() % m;
}
for (p = 0; p < j; p++)
{
if (a[n] == b[o])
{
printf("YES");
}
else
{
printf("NO");
}
}
return 0;
}
Thanks for the help!

It is unclear what you are trying to achieve from the rand() function but certainly you need now to find different permutations to do that. Permutations of string s1 should be equal to string s2 which means all character in string s1 should be present in s2 and count of each of those characters in both the strings should be same
Here is a working version:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
//CHECKING IF STRING TWO IS ANY PERMUTATION OF STRING ONE
int main()
{
char str_one[]="abbcd";
char str_two[]="bcab";
int arr[26]={0};
int index=0;
int len_one=strlen(str_one);
int len_two=strlen(str_two);
int val;
if(len_one!=len_two)
{
printf("NO");
exit(0);
}
while(index<len_one)
{
++arr[str_one[index++]-'a'];
}
index=0;
while(index<len_two)
{
--arr[str_two[index++]-'a'];
if(arr[str_two[index]-'a']<0)
{
printf("NO");
exit(0);
}
}
index=0;
while(index<26)
{
if(arr[index]!=0)
{
printf("NO");
exit(0);
}
++index;
}
printf("yes");
return 0;
}

As you only want some suggestions about the improving your code.
You may use scanf("%20s", str1) or something like that to improve the memory footprint of your answer. You will need to use a loop to read the strings. %20s asks scanf to read 20 characters at most. You can tailor the number according to your needs.
You can get the length of the string via strlen function included from string.h.
You just want to check the occurrence times of each character. In your case you can use an integer array of length 26, or two depending on your algorithm.
Use better variable names. This really helps if you do something wrong in algorithm.
This would be my solution just for one string comparision
Detailed Evaluation of User Code
for (j = 0; j < i; j++)
{
scanf("%s %s", a, b);
}
This code block reads all lines. C is evaluated sequentially, so instead you will need to do this like
for (j = 0 ; j < i ; j++)
{
scanf("%s %s", a, b);
/* do comparision for each here */
}
As I mentioned above C is evaluated sequentially, so the next 2 for loops also evaluates and results in a randomly selected 2 characters from both strings. I did not analyzed the probability, but from my senses I can say it won't hit same character most of the time. It is better to loop over a string, than pray for RNG to hit.
for (k = 0; a[k] != '\0'; k++)
{
n = rand() % k;
}
for (m = 0; b[m] != '\0'; m++)
{
o = rand() % m;
}
The above code will execute and only produces 1 output for each for loop and due to randomness of it I cannot tell which outcome it will lead.
for (p = 0; p < j; p++)
{
if (a[n] == b[o])
{
printf("YES");
}
else
{
printf("NO");
}
}
This for loop will execute exactly i times as the current value of j will be i as the first for loop executed before. Each of these loops will compare the same a[n] and b[o] from the reasons explained above. so the outcome will be YESxi or NOxi. No matter what the strings are.
Hope this explains what is wrong with your code.

For compare two string use of strcmp() :
int strcmp(const char *str1, const char *str2)
Parameters :
str1 − This is the first string to be compared.
str2 − This is the second string to be compared.
Return Value :
This function return values that are as follows :
if Return value < 0 then it indicates str1 is less than str2.
if Return value > 0 then it indicates str2 is less than str1.
if Return value = 0 then it indicates str1 is equal to str2.
Example :
#include <stdio.h>
#include <string.h>
int main () {
char str1[15];
char str2[15];
int ret;
strcpy(str1, "abcdef");
strcpy(str2, "ABCDEF");
ret = strcmp(str1, str2);
if(ret < 0) {
printf("str1 is less than str2");
} else if(ret > 0) {
printf("str2 is less than str1");
} else {
printf("str1 is equal to str2");
}
return(0);
}

Related

Array goes of out of bounds without giving any errors

My professor asked me to make a Codebreaker game in C. (User is breaking the code by guessing original code. original code is given as a cmd-line arg.After every attempt;(b, w): the number of correct colors in the correct positions (b) and the number of colors that are part of the code but not in the correct positions (w) are printed as Feedback.)Only standard input and output is allowed. I got it working, but the arrays Secret_Code2 and guess2 goes out of bounds. It has some strange behaviours like changing int variables causes changes in arrays even they are independent. I'm aware that C does not check array bounds, is there any improvements that i can make?
Here is my code;
#include <stdio.h>
#define Max_Attempts 12
char *Sectret_CODE = NULL;
int main(int argc,char **argv)
{
//Definitions
printf("Available Colors: (B)lue (G)reen (O)range (P)urple (R)ed (Y)ellow\n\n");
//Getting input and validating
if(argc != 2)
{
fprintf(stderr,"Invalid input\n");
return 1;
}
Sectret_CODE = argv[1];
int i = Max_Attempts;
int Won = 0;
while (i > 0 && !Won)
{
int b = 0, w = 0, t=0;
char guess[4];
char Sectret_CODE2[4];
char guess2[4];
printf("No. guesses left: %i\n",i);
printf("Enter Your Guess: ");
scanf("%s",guess);
//printf("%s",guess);
for(int j = 0; j < 4; j++)
{
//printf("%s,%s\n",Sectret_CODE2,guess2);
if(Sectret_CODE[j] == guess[j])
{
b++;
}
else
{
Sectret_CODE2[t] = Sectret_CODE[j];
guess2[t] = guess[j];
t++;
printf("%s,%s,%i\n",Sectret_CODE2,guess2,t);
}
}
int s = t;
//printf("%i",t);
Sectret_CODE2[t] = '\0' ;
guess2[t] = '\0' ;
if(b == 4)
{
printf("You Won\n");
Won = 1;
return 0;
}
else
{
for(int j = 0; j < s; j++)
{
for(int k = 0; k < s;k++)
if(Sectret_CODE2[j] == guess2[k])
{
w++;
break;
}
}
}
printf("Feedback: %i,%i\n",b,w);
i--;
}
if(!Won)
{
printf("You Lose!\n");
}
}
You aren't allocating space for the terminating null character in your character arrays. Each array needs to hold up to 4 values, plus a terminating null character. So you need to declare them to hold 4+1 = 5 characters. Otherwise writing the null character can write past the end of the arrays.
Also, inside your loop, you are attempting to print those arrays using printf with %s before null-terminating them. You need to null-terminate them, at the proper point, before printing them with %s.

The goal is to read two strings into 2 different variables. Then we count the number of "C" in each string and output the result

Here is what I did:
int main ()
{
int count = 0;
int i, j;
char firstLine[10000000];
char secondLine[10000000];
scanf("%s", firstLine);
scanf("%s", secondLine);
for (i=0;i<10000000;i++) {
if (firstLine[i] == 'C') {count++;}
}
for (j=0;j<10000000;j++) {
if (secondLine[j] == 'C') {count++;}
}
printf("%d", count);
return 0;
}
I think it makes sense but there is some sort of segmentation error according to my compiler. What am I missing?
For example, an input of AB
BBAAB should yield an output of 0.
Something like this should do the trick:
#define BUF_MAX 100
int main ()
{
int count1 = 0, count2 = 0;
char firstLine[BUF_MAX];
char secondLine[BUF_MAX];
fgets(firstLine,BUF_MAX,stdin);
for (int i = 0; firstLine[i] != 0; ++i)
if (firstLine[i] == 'C') ++count1;
fgets(secondLine,BUF_MAX,stdin);
for (int i = 0; secondLine[i] != 0; ++i)
if (secondLine[i] == 'C') ++count2;
printf("String 1 has %d C's\n", count1);
printf("String 2 has %d C's\n", count2);
return 0;
}
The BUF_MAX sets the maximum size of each line buffer, which I chose to be 100 (99 characters + the terminating null). If this isn't enough, make it bigger... say 500. But 10,000,000 is absurd... that could be the complete text of all of the Harry Potter books combined, or perhaps the complete works of Shakespeare!
The for loops continue as long as the character in the string is non-zero, i.e. until the terminating null character is encountered.
You should stop counting (break;) when you find a 0-terminator in your lines.
At the moment, you are going through an uninitialized garbage looking for random C

A program that prints even and odd characters from a string

This is for Homework
I have to write a program that asks the user to enter a string, then my program would separate the even and odd values from the entered string. Here is my program.
#include <stdio.h>
#include <string.h>
int main(void) {
char *str[41];
char odd[21];
char even[21];
int i = 0;
int j = 0;
int k = 0;
printf("Enter a string (40 characters maximum): ");
scanf("%s", &str);
while (&str[i] < 41) {
if (i % 2 == 0) {
odd[j++] = *str[i];
} else {
even[k++] = *str[i];
}
i++;
}
printf("The even string is:%s\n ", even);
printf("The odd string is:%s\n ", odd);
return 0;
}
When I try and compile my program I get two warnings:
For my scanf I get "format '%s' expects arguments of type char but argument has 'char * (*)[41]". I'm not sure what this means but I assume it's because of the array initialization.
On the while loop it gives me the warning that says comparison between pointer and integer. I'm not sure what that means either and I thought it was legal in C to make that comparison.
When I compile the program, I get random characters for both the even and odd string.
Any help would be appreciated!
this declaration is wrong:
char *str[41];
you're declaring 41 uninitialized strings. You want:
char str[41];
then, scanf("%40s" , str);, no & and limit the input size (safety)
then the loop (where your while (str[i]<41) is wrong, it probably ends at once since letters start at 65 (ascii code for "A"). You wanted to test i against 41 but test str[i] against \0 instead, else you get all the garbage after nul-termination char in one of odd or even strings if the string is not exactly 40 bytes long)
while (str[i]) {
if (i % 2 == 0) {
odd[j++] = str[i];
} else {
even[k++] = str[i];
}
i++;
}
if you want to use a pointer (assignement requirement), just define str as before:
char str[41];
scan the input value on it as indicated above, then point on it:
char *p = str;
And now that you defined a pointer on a buffer, if you're required to use deference instead of index access you can do:
while (*p) { // test end of string termination
if (i % 2 == 0) { // if ((p-str) % 2 == 0) { would allow to get rid of i
odd[j++] = *p;
} else {
even[k++] = *p;
}
p++;
i++;
}
(we have to increase i for the even/odd test, or we would have to test p-str evenness)
aaaand last classical mistake (thanks to last-minute comments), even & odd aren't null terminated so the risk of getting garbage at the end when printing them, you need:
even[k] = odd[j] = '\0';
(as another answer states, check the concept of even & odd, the expected result may be the other way round)
There are multiple problems in your code:
You define an array of pointers char *str[41], not an array of char.
You should pass the array to scanf instead of its address: When passed to a function, an array decays into a pointer to its first element.
You should limit the number of characters read by scanf.
You should iterate until the end of the string, not on all elements of the array, especially with (&str[i] < 41) that compares the address of the ith element with the value 41, which is meaningless. The end of the string is the null terminator which can be tested with (str[i] != '\0').
You should read the characters from str with str[i].
You should null terminate the even and odd arrays.
Here is a modified version:
#include <stdio.h>
int main(void) {
char str[41];
char odd[21];
char even[21];
int i = 0;
int j = 0;
int k = 0;
printf("Enter a string (40 characters maximum): ");
if (scanf("%40s", str) != 1)
return 1;
while (str[i] != '\0') {
if (i % 2 == 0) {
odd[j++] = str[i];
} else {
even[k++] = str[i];
}
i++;
}
odd[j] = even[k] = '\0';
printf("The even string is: %s\n", even);
printf("The odd string is: %s\n", odd);
return 0;
}
Note that your interpretation of even and odd characters assumes 1-based offsets, ie: the first character is an odd character. This is not consistent with the C approach where an even characters would be interpreted as having en even offset from the beginning of the string, starting at 0.
Many answers all ready point out the original code`s problems.
Below are some ideas to reduce memory usage as the 2 arrays odd[], even[] are not needed.
As the "even" characters are seen, print them out.
As the "odd" characters are seen, move them to the first part of the array.
Alternative print: If code used "%.*s", the array does not need a null character termination.
#include <stdio.h>
#include <string.h>
int main(void) {
char str[41];
printf("Enter a string (40 characters maximum): ");
fflush(stdout);
if (scanf("%40s", str) == 1) {
int i;
printf("The even string is:");
for (i = 0; str[i]; i++) {
if (i % 2 == 0) {
str[i / 2] = str[i]; // copy character to an earlier part of `str[]`
} else {
putchar(str[i]);
}
}
printf("\n");
printf("The odd string is:%.*s\n ", (i + 1) / 2, str);
}
return 0;
}
or simply
printf("The even string is:");
for (int i = 0; str[i]; i++) {
if (i % 2 != 0) {
putchar(str[i]);
}
}
printf("\n");
printf("The odd string is:");
for (int i = 0; str[i]; i++) {
if (i % 2 == 0) {
putchar(str[i]);
}
}
printf("\n");
here is your solution :)
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[41];
char odd[21];
char even[21];
int i = 0;
int j = 0;
int k = 0;
printf("Enter a string (40 characters maximum): ");
scanf("%s" , str);
while (i < strlen(str))
{
if (i % 2 == 0) {
odd[j++] = str[i];
} else {
even[k++] = str[i];
}
i++;
}
odd[j] = '\0';
even[k] = '\0';
printf("The even string is:%s\n " , even);
printf("The odd string is:%s\n " , odd);
return 0;
}
solved the mistake in the declaration, the scanning string value, condition of the while loop and assignment of element of array. :)

delete repetition in strings

i want to write code in c language to delete any character in string s1 which matches any character in the string s2 . using only for loops. that is my trial has failed -_- .
for example if s1="ahmed" and s2="omnia" should edit s1 to >> s1="hed"
#include <stdio.h>
#include <stdlib.h>
int i,j;
int k;
int counter=0;
int main()
{
char s1[100];
char s2[10];
char temp[100];
printf("\n enter string 1: ");
scanf("%s",s1);
printf("\n enter string 2: ");
scanf("%s",s2);
printf("\n%s",s1);
printf("\n%s",s2);
for(j=0;j<9;j++)
{
for(i=0;i<9;i++)
{
if(s1[i]!=s2[j]&&s1[i]!='\0')
{
temp[counter++]=s1[i]; //add unique items to temp
k=counter; //size
temp[counter]='\0';
}
}
}
for(i=0;i<k;i++)
{
s1[i]=temp[i];
}
printf("\nstring 1 after delete : ");
printf("%s",s1);
return 0;
}
how can i compare one item with nested items then achieve a condition ??
Why are you including the null character statements inside the if statement?
Try these two statements after the two for loops, like this. And please indent your code.
for(j=0;j<strlen(s1);j++) //Why is it 9 in your code? It should be the respective lengths
{
for(i=0;i<strlen(s2);i++)
{
if(s1[i]!=s2[j]&&s1[i]!='\0')
{
temp[counter++]=s1[i];
}
}
}
k=counter;
temp[counter]='\0';
and include:#include<string.h>
I don't see any coding errors here, only your logic is flawed.
This should work
for (j = 0; j < 9; j++)
{
for (i = 0; i < 9; i++)
{
if (s1[j] == s2[i] && s1[i] != '\0')
{
break;
}
else if (i == strlen(s2))
{
temp[counter++] = s1[j];
}
}
}
temp[counter] = '\0';
for (i = 0; i < counter; i++)
{
s1[i] = temp[i];
}
printf("\nstring 1 after delete : ");
printf("%s", s1);
In your original code you kept reading the original string from the beginning, instead of advancing the iterator each time.
So in the first iteration you compared 'ahmed' against 'omnia' which is fine.
In the second iteration though, you compared 'ahmed' against 'omnia', instead of 'hmed' against 'omnia', and that's why you got a large repetition of the original string in your output.
Also, I'd memset the memory of s1 and s2 first to 0.

Strings (C) - Comparing letters of two strings

Trying to write that function checks whether all the letters in word appear in s, in the same order. If a letter appears several times in word, then it should appear
at least as many times in s.
For example:
containsLetters2("abcdef", "aaabbb")
returns 0 because there are no three appearances of the letter "a" followed by three appearances of the letter “b”.
This:
containsLetters2("axaxxabxxbxbcdef","aaabbb")
returns 1
I can't understand whats wrong in my code:
int containsLetters2(char *s, char *word)
{
int j,i, flag;
long len_word, len_s;
len_s=strlen(s);
len_word=strlen(word);
for (i=0; i<=len_word; i++) {
flag=0;
for (j=0; j<=len_s; j++) {
if (*word==*s) {
flag=1;
word++;
break;
}
s++;
}
if (flag==0) {
break;
}
}
return flag;
}
int main() {
char string3[MAX_STRING] , string4[MAX_STRING];
printf("Enter 2 strings for containsLetters2\n");
scanf ("%s %s", string3, string4);
printf("Return value from containsLetters2 is: %d\n",containsLetters2(string3,string4));
return 0; }
for (i=0; i<=len_word; i++) {
flag=0;
for (j=0; j<=len_s; j++) {
if (*word==*s) {
You have two obvious problems. One is an off by one error. If the length is 10, then your code processes elements from 0 to 10, which is 11 elements, not 10. Second, you keep comparing *word to *s. What you want is word[i] compared to s[j].
There are lots more problems that are not as obvious. I'd strongly suggest you take a step back and start by documenting the algorithm your code is supposed to follow. That will make it easier to debug the code as you will know precisely what it is supposed to be doing.
The following code may not compile, but will do what you want it to do, hope it helps:
int containsLetters2(char *s, char *word) {
int lastIndex = 0;
for (int i = 0; i < strlen(word); i++) {
for (; lastIndex < strlen(s) && s[lastIndex] != word[i]; lastIndex++);
if (lastIndex == strlen(s)) {
return 0;
}
}
return 1;
}
You should preserve the value of variable j,
For example,
word = "aaabbb"
s = "axaxxabxxbxbcdef"
The 1st iteration, word[1] == s[1], then it break and come to the 2nd iteration,
at this time, j is reset to zero, and word[2] == s[1].
This got to be wrong.
Change your code as below to see if it helps,
i=j=0;
for (; i<len_word; i++) {
flag=0;
for (; j<len_s; j++) {
if (*word==*s) {
flag=1;
word++;
break;
}
s++;
}
if (flag==0) {
break;
}
}

Resources