Rotated strings - c

Write code to check if s2 is rotation of s1 using only one call to isSubString (ie. waterbottle is a rotation of erbottlewat).
I write program for this but i can't able to get the desired output. Please guide me where I am going wrong.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int isRotated(char *s1, char *s2);
int isSubstring(char *s1, char *s2);
int isRotated(char *s1, char *s2)
{
int r;
char s[100];
if(strlen(s1) == strlen(s2))
strcpy(s, s1);
r = isSubstring(s, s2);
strcat(s, s1);
return r;
}
int isSubstring(char *s1, char *s2){
if(strstr(s1, s2))
return 1;
else
return 0;
}
int main(void) {
char s1[100], s2[100];
printf("Enter the first String\n");
scanf("%s", s1);
printf("Enter the second String\n");
scanf("%s", s2);
if(isRotated(s1, s2)==1)
printf("%s and %s are rotated string\n", s1, s2);
else
printf("%s and %s are not rotated string\n", s1, s2);
return 0;
}

To check if s2 is rotation of s1, you may want to concentrate two s1s, and try finding s2 in the new string.
It is necessary to check the length of s1 and s2. For example, s1 is "ABCD", s2 is "CDA". Then s is "ABCDABCD". strstr(s, s2) == 1, but obviously, s2 isn't rotation of s1.
Also, I'd want to call strcmp() first, because I consider a "ABCD" as rotation of "ABCD" itself. However, this is only a matter of definition.
int isRotated(char *s1, char *s2)
{
char s[199];
if(strlen(s1) != strlen(s2))
return 0;
else if(strcmp(s1, s2) == 0)
return 1;
else
strcpy(s, s1);
strcat(s, s1);
return isSubString(s, s2);
}
BTW: "substring" is one word, so it might be better changing isSubString() to isSubstring()

If you do the comparison with strstr() you are searching a substring in the rotated string. So what you are doing is to find for example the string s1 ABCD in an other string s2 CDAB. So in fact s2 has no substring s1 in it and your function int isSubString(char *s1,char *s2) will always return false.
A simple solution for this would be not to compare s1 with s2 directly. You have to compare s2 to a doubled copy of s1: CDABCDAC, there you can see that this string contains a substring ABCD and your function will return true.
This would mean for your function:
int isRotated(char *s1,char *s2)
{
char s[200];
strcpy(s,s1); // Copy content of s1 to s
strcat(s,s1); // Append s again with the content of s1
if(strstr(s,s2))
return 1;
else
return 0;
}

How about this, using the concatenate-and-look-for-substring approach:
int isRotated(const char *s1, const char *s2)
{
const size_t l1 = strlen(s1);
const size_t l2 = strlen(s2);
if(l1 != l2)
return 0;
char joined[2 * l1 + 1];
memcpy(joined, s1, l1);
memcpy(joined + l1, s1, l1);
joined[2 * l1] = '\0';
return strstr(joined, s2) != NULL;
}
Basically uses more const, variable-length array to handle varying lengths, and memcpy() when we know the length we're copying.

Related

Need advice (hint) or help create 2 string function

The function receives two strings str1 and str2 and returns an integer. The function will insert the str2 string at the beginning of the str1 string. When the str1 string size will not change. If the length of the str1 string can contain the entire str2 string, the function will change str1 to contain str2 and then The letters of str1 up to the original length of str1. In this case the function will return 1. If the str2 string is longer than str1, the first letters of str2 will be placed in the str1 string up to str1, In this case the function will return 0.
Example 1:
str1 = "abcdefgh" str2 = "xyz"
After running the function:
str1 = "xyzabcde"
And the function will return 1.
Example 2:
str1 = "abcd" str2 = "efghj"
After running the function:
str1 = "efgh"
And the function will return 0
I started this one
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int string_pre(char *str1, char *str2) {
int sizeStr1 = strlen(str1);
int sizeStr2 = strlen(str2);
}
int main() {
char str1[]= "abcdefgh";
char str2[]= "xyz";
string_pre(str1, str2);
printf("After concatenation: %s %s \n", str1, str2);
printf("After concatenation: %s \n", str2);
return 0;
}
Not sure if this is the correct way to start.
You have a good start. You might use size_t instead of int for the string lengths and define str2 as const char *str2 as it is not modified in the function so you can accept constant strings for this argument. Next should come a test if the length of str1 is greater or equal to the length of str2 and appropriate action should be taken in both cases.
Note that your main function should test multiple cases and print the return value too.
Here is a modified version:
#include <stdio.h>
#include <string.h>
int string_pre(char *str1, const char *str2) {
if (*str2 == '\0') { // quick test for trivial case
return 1;
} else {
size_t sizeStr1 = strlen(str1);
size_t sizeStr2 = strlen(str2);
if (sizeStr1 >= sizeStr2) {
memmove(str1 + sizeStr2, str1, sizeStr1 - sizeStr2);
memcpy(str1, str2, sizeStr2);
return 1;
} else {
memcpy(str1, str2, sizeStr1);
return 0;
}
}
}
int main() {
char str1[]= "abcdefgh";
char str2[]= "xyz";
char str3[]= "xyzxyzxyzxyz";
char str4[]= "ABCDEFGH";
int n1 = string_pre(str1, str2);
printf("test1: n1=%d str1='%s' str2='%s'\n", n1, str1, str2);
int n2 = string_pre(str1, str3);
printf("test2: n2=%d str1='%s' str3='%s'\n", n2, str1, str3);
int n3 = string_pre(str1, str4);
printf("test3: n3=%d str1='%s' str4='%s'\n", n3, str1, str4);
return 0;
}
Output:
test1: n1=1 str1='xyzabcde' str2='xyz'
test2: n2=0 str1='xyzxyzxy' str3='xyzxyzxyzxyz'
test3: n3=1 str1='ABCDEFGH' str4='ABCDEFGH'
This should do the work.
however - using strlen to determine the length of a string buffer is normally a bad practice, as you may use buffers that are larger than the actual string they store. a more c way would be to pass on the length of buffer available.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int string_pre(char *str1,char *str2)
{
size_t sizeStr1 = strlen(str1);
size_t sizeStr2 = strlen(str2);
long chars_to_move_right = sizeStr1 - sizeStr2;
size_t chars_to_copy = sizeStr2 > sizeStr1 ? sizeStr1 : sizeStr2;
// have to use memmove since the copying may overlap
if (chars_to_move_right > 0)
{
memmove(str1 + sizeStr2, str1, chars_to_move_right);
}
// no overlap expected here, and memcpy may be more efficient.
memcpy(str1, str2, chars_to_copy);
return sizeStr1 >= sizeStr2;
}
int main()
{
char str1[]= "abcdefgh";
char str2[]= "xyz";
printf("Before concatenation: '%s' '%s' \n",str1,str2);
int res = string_pre(str1,str2);
printf("After concatenation: '%s' '%s' \n",str1,str2);
printf("Result = %d\n", res);
return 0;
}
Not sure if this is the correct way to start.
For starters neither declaration from the header <stdlib.h> is used in your program. So you may remove it.
The second function parameter must be declared with qualifier const because the corresponding string is not changed within the function.
int string_pre(char *str1, const char *str2);
The return type of the function strlen is size_t. So the variables sizeStr1 and sizeStr2 must be declared as having the type size_t.
size_t sizeStr1 = strlen(str1);
size_t sizeStr2 = strlen(str2);
Now all is ready to fill the body of the function with a code as for example :)
#include <stdio.h>
#include <string.h>
int string_pre( char *s1, const char *s2 )
{
size_t n1 = strlen( s1 );
size_t n2 = strlen( s2 );
int moved_right = n2 < n1;
if ( moved_right )
{
memmove( s1 + n2, s1, n1 - n2 );
}
else
{
n2 = n1;
}
memcpy( s1, s2, n2 );
return moved_right;
}
int main( void )
{
char s1[] = "abcdefgh";
char s2[] = "xyz";
int result = string_pre( s1, s2 );
printf( "%d: %s\n", result, s1 );
char s3[] = "abcd";
char s4[] = "efghj";
result = string_pre( s3, s4 );
printf( "%d: %s\n", result, s3 );
}
The program output is
1: xyzabcde
0: efgh
If in case when the both strings are equal each other and you need to return 1 then in this case change this line
int moved_right = n2 < n1;
for example to this line
int moved_right = !( n1 < n2 );
Strictly speaking the function should be declared like
int string_pre(char * restrict str1, const char * restrict str2);
Rather than run the maximum length of both strings, how about iterating no more than the length of the first string?
int replace(char *str1, const char *str2) {
size_t len1 = strlen(str1);
// Search for the null character, but only so far.
const char *end = memchr(str2, '\0', len1);
size_t len2 = (end == NULL) ? len1 : end - str2;
// At this point len2 <= len1
memmove(str1 + len2, str1, len1 - len2); // Shift str1
memmove(str1, str2, len2); // Copy in str2
return str2[len2] == '\0'
}

C -swap 2 chars recursively with only one pointer

I need to write a function:
void swap (char * s1, char * s2);
The function will replace the contents of both strings 1s and 2s.
Constraints:
In the function, there is no use of [] anywhere, but performance by working with pointers, in addition, trips must be made with the voters, meaning that they will actually move to another cell as needed, and will not remain in the same location all the time.
• No loops in the function, that is, work in recursion.
I did the function with pointer to pointer str** but must change it to only one pointer str and recursively. How can I change it?
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *str1="abc",*str2="xyz",*pRev;
swap(&str1, &str2);
printf("str1 is %s, str2 is %s", str1, str2);
getchar();
return 0;
}
//need *str NOT **str
void swap(char **str1, char **str2);
char * RevWords (char * str, int size);
void swap(char **str1, char **str2)
{
char *temp = *str1_ptr;
*str1_ptr = *str2_ptr;
*str2_ptr = temp;
}
after swap method:
str2="abc", str1="xyz"
Well this is clearly not an ideal solution but gives you something to work with.
However this will only work (as mentioned above) when you have the same length of strings (or yes, you'll have to allocate memory + you'd need to know the length of your strings). But otherwise I think this may answer your question.
This is working with recursion and depends on the fact that both strings are the same length and containing a zero character at the end of each one.
#include <stdio.h>
#include <stdlib.h>
void swap(char* str1, char* str2)
{
// if both of them are zero characters then stop
if (*str1 == '\0' && *str2 == '\0')
return;
// else swap the contents of the pointers
else
{
char tmp = *str1;
*str1 = *str2;
*str2 = tmp;
// advance both pointer and swap them too if thye are not '\0'
swap(++str1, ++str2);
}
}
int main()
{
char str1[] = "abc\0\0\0"; // padded with zeros to be the same length as str2
char str2[] = "xyz123"; // the last '\0' is automatically added
swap(str1, str2);
printf("str1 is %s, str2 is %s", str1, str2);
getchar();
return 0;
}

whats wrong with my code(copying string using pointers?)?

//a function that copies one string to another
copy(char *,char*);
main()
{
char one[20],two[20];
printf("enter two sentences \n\n");
gets(one);//first string
gets(two);//second string
copy(one,two);
printf("%s",two);
}
copy(char *s1,char *s2)
{
while(*s1!='\0')
{
s2=s1;
s1++;
s2++;
}
s2='\0';
}
what wrong with the above program ? why the string 'one' is not getting copied to string 'two'?please explain with the help of pointer
It's because this:
s2 = s1;
changes the pointer s2 so that it points to the content of s1.
What you want to do is copy the content:
*s2 = *s1;
A decent compiler should also have given you a warning on this line:
s2 = '\0';
since you're assigning a char to a char *. It should be:
*s2 = '\0';
Enacting those changes, the function would then be (including using some, IMNSHO, better variable names):
void copy (char *from, char *to) {
while (*from != '\0') {
*to = *from;
from++;
to++;
}
*to = '\0';
}
Or, once your brain has been warped by several decades of C use like mine :-)
void copy (char *from, char *to) {
while (*to++ = *from++);
}
#include <stdio.h>
#include <string.h> /* for strchr */
void copy(const char *, char*); /* use void to return nothing */
int main(void) /* main() is not valid */
{
char one[20], two[20];
char *ptr;
printf("enter two sentences \n\n");
/* gets is deprecated, use fgets in order to avoid overflows */
fgets(one, sizeof one, stdin);
/* fgets leaves a trailing newline, remove it */
if ((ptr = strchr(one, '\n'))) *ptr = '\0';
fgets(two, sizeof two, stdin); /* why? is gonna be replaced by one */
copy(one, two);
printf("%s\n", two);
return 0;
}
void copy(const char *s1, char *s2) /* s1 is not modified, use const */
{
while(*s1 != '\0')
{
*s2 = *s1; /* Don't assign addresses, assign values */
s1++;
s2++;
}
*s2 = '\0';
}

C return value using argument to function

I'm trying to run function which will return two strings by passing a pointer to them:
#include <stdio.h>
void gen_str(char *str1, char *str2){
char *s1 = "abcd";
char *s2 = "defg";
str1= strdup(s1);
str2= strdup(s2);
printf("\n\r str1 %s str2 %s\n\r", str1, str2);
}
int main(void){
char *s1, *s2;
gen_str(s1, s2);
printf("\n\r s1 %s s2 %s\n\r", s1, s2);
return 0;
}
where output is:
str1 abcd str2 defg
s1 8, s2 8,
Can someone tell me, what I'm doing wrong? I thought that strdup() will alloc memory for my new strings, and return pointers filled with strings. But actual behavior is different. So I'm asking for help.
You need your function to modify the pointers s1 and s2, so you need to pass their addresses, so that the function can modify the originals, not a copy.
void gen_str(char **str1, char **str2){
char *s1 = "abcd";
char *s2 = "defg";
*str1= strdup(s1);
*str2= strdup(s2);
printf("\n\r str1 %s str2 %s\n\r", *str1, *str2);
}
int main(void){
char *s1, *s2;
gen_str(&s1, &s2);
printf("\n\r s1 %s s2 %s\n\r", s1, s2);
return 0;
}
Note also that you need to free these strings at some point, otherwise you have a memory leak.
You got your pointers confused. The basic type for a C string is already char*, and now you want a pointer to that, i.e. a char**:
void fill_me(char ** ps)
{
const char * t = "hello";
*ps = strdup(t);
}
/* elsewhere */
char * s;
fill_me(&s);
Moral: If you want a function to modify an argument passed by the caller, the caller needs to take the address-of (&) something at some point.
You're only changing the pointer inside the function. To change it outside the function, you'll need to pass the function the address of the two strings, like this:
#include <stdio.h>
void gen_str(char **str1, char **str2){
char *s1 = "abcd";
char *s2 = "defg";
*str1= strdup(s1);
*str2= strdup(s2);
printf("\n\r str1 %s str2 %s\n\r", *str1, *str2);
}
int main(void){
char *s1, *s2;
gen_str(&s1, &s2);
printf("\n\r s1 %s s2 %s\n\r", s1, s2);
return 0;
}
You can's use the value of a variable before you've initialized it!
char *s1, *s2;
gen_str(s1, s2);
The first line doesn't assign any particular values to s1 and s2. But then you pass them to gen_str. To have another function fill in the value of a variable, pass a pointer to that variable to the function, not its value.
#include <stdio.h>
#include <string.h>
void gen_str(char **str1, char **str2){
const char *s1 = "abcd";
const char *s2 = "defg";
*str1 = strdup(s1);
*str2 = strdup(s2);
printf("\n str1 %s str2 %s\n", *str1, *str2);
}
int main(void){
char *s1, *s2;
gen_str(&s1, &s2);
printf("\n s1 %s s2 %s\n", s1, s2);
free(s1);
free(s2);
return 0;
}

Is there a function in C to find a substring overlap?

in C, is there a function that when giver two strings, will return the substring overlap or size of the overlap? So like something that does:
char s1[5] = {cart};
char s2[4] = {car};
int overlap;
overlap = get_overlap(s1, s2); /*or have overlap be a string if it returns the overlap*.
and then overlap would be 3.
If not, how do i make one that will return the int value of the overlap.
Use strstr. Example from link:
/* strstr example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="This is a simple string";
char * pch;
pch = strstr (str,"simple");
strncpy (pch,"sample",6);
puts (str);
return 0;
}
Output:
This is a sample string
Note:
The entire substring will be matched ; note that strstr does not do partial matches.
char *strstr(const char *str1, const char *str2);
The function strstr() finds the
occurrence of str2 in the str1 and
returns the pointer to occurrence of
str2 in str1. If no match found, then
a null pointer is returned.
Qualification: This function computed overlaps of the type
string1
ng1randomcharacters
In this case, the overlap is 3
// Traverses s1 from left to right and s2 from left to right, looking for overlap
int get_overlap(char *s1, char *s2)
{
int u2 = strlen(s2)-1;
int p1 = strlen(s1)-1;
int p2 = 0;
while( p1>=0 && p2<=u2 )
{
if (s1[p1--] != s2[p2++])
{
--p2; // no overlap, so correct for incremented value
break;
}
}
return(p2);
}
There's no builtin function, but it's pretty simple to write:
size_t overlap(const char *s1, const char *s2)
{
size_t i = 0;
while (s1[i] && s2[i] && s1[i] == s2[i])
i++;
return i;
}

Resources