Recursion: Reverse string in its position - c

Recursion. I checked other online solutions and they seem to be pretty much identical to mine.
The code should reverse the string (in its position) but it does not. E.g when input is st2 = "abcdefg" the output is an empty string. I was expecting st2 = "gfedcba". What am i missing?
#include <stdio.h>
#include <string.h>
void recurse_reverse(char s[], int sz)
{
int i=0,j = sz -1;
if(i<j)
{
swap(&s[i],&s[j]);
recurse_reverse(s+1, sz-2);
}
}
void swap( char* s1, char *s2)
{
char tmp;
tmp = *s1;
*s1 = *s2;
*s2 = tmp;
}
int main(void)
{
char st1[9] = "abcdefg", st2[9];
strcpy(st2,st1);
recurse_reverse(st2,9);
printf("s1 = %s\ns2 = %s",st1,st2);
printf("\n" );
return 0;
}

You are swapping the 2 zero bytes at the end of st1. Hence, the st2 starts with a null byte and thus the printf() isn't printing anything.
You just need to fix your argument passing. Instead of
recurse_reverse(st2,9);
do
recurse_reverse(st2,strlen(st1));
You probably want to add logic to make sure your destination array st2 has sufficient space.

I added a printf statement to debug the issue and got the below output. You are trying to access 9th variable which is a terminated null character \0 hence you only get \0 as output and not the actual reversed string.
Instead of hardcoding the size of string you can use strlen to get the string length.
1st char = a and 9th char is ▒
1st char = b and 9th char is
1st char = c and 9th char is g
1st char = d and 9th char is f
s1 = abcdefg
s2 = ▒
Solution
Intended code change
recurse_reverse(st2,strlen(st1));
Output
1st char = a and 9th char 9th char is g
1st char = b and 9th char 9th char is f
1st char = c and 9th char 9th char is e
s1 = abcdefg
s2 = gfedcba

#include <stdio.h>
#include <string.h>
void swap( char* s1, char *s2);
void recurse_reverse(char s[], int sz)
{
int i=0,j = sz-1;
if(i<j)
{
swap(&s[i],&s[j]);
recurse_reverse(s+1, sz-2);
}
}
void swap( char* s1, char *s2)
{
char tmp;
tmp = *s1;
*s1 = *s2;
*s2 = tmp;
}
int main(void)
{
char st1[9] = "abcdefg", st2[9];
int len=0;
strcpy(st2,st1);
len =strlen(st2);
recurse_reverse(st2,len);
printf("s1 = %s\ns2 = %s",st1,st2);
printf("\n" );
return 0;
}

Related

Copy a string to another string

I am following this algorithm that will copy one string to another string:
[S is a source string and T is a target string]
1. Set I = 0
2. Repeat step 3 while S[I] ≠ Null do
3. T[I] = S[I]
4. I = I + 1
[End of loop]
5. Set T[I] = Null
6. Return
I have attempted it but it instead removes the first n characters from source string relative to length of target string. For example:
#include <stdio.h>
#include <stdlib.h>
char const* stringCopy(char* T, char const* S){
while(*S){
*T++ = *S++;
}
//*T = 0;
return T;
}
int main(void){
char sentence[100] = "some sentence";
char* again = "another";
printf("%s", stringCopy(sentence, again));
return EXIT_SUCCESS;
}
You return the incremented original pointer T. Make a copy of T for the copy loop and return the original pointer.
#include <stdio.h>
#include <stdlib.h>
char const* stringCopy(char* T, char const* S){
char *ptr = T;
while(*ptr++ = *S++);
return T;
}
int main(void){
char sentence[100] = "some sentence";
char* again = "another";
printf("%s", stringCopy(sentence, again));
return EXIT_SUCCESS;
}

Trying to create a strcat in c

So, I'm trying to code a strcat function using pointers, just for studying purposes.
#include <stdio.h>
#include <string.h>
char *strcpyy(char *dest, char *orig){
char *tmp = dest;
while (*dest++ = *orig++);
return tmp;
}
char *strcatt(char *dest, char *orig){
strcpyy(dest + strlen(dest), orig);
return dest;
}
int main(){
char *a = "one";
char *b = "two";
printf("%s", strcatt(a,b));
}
When I run this code, the output is empty. Can anyone point out the problem?
String literals are read-only. Any attempt to write to a string literal will invoke undefined behavior, which means that your program may crash or not behave as intended.
Therefore, you should not use a pointer to a string literal as the first argument to strcat or your equivalent function. Instead, you must provide a pointer to an object which is writable and has sufficient space for the result (including the terminating null character), for example a char array of length 7. This array can be initialized using a string literal.
Therefore, I recommend that you change the line
char *a = "one";
to the following:
char a[7] = "one";
After making this change, your program should work as intended.
You declared two pointers to string literals
char *a = "one";
char *b = "two";
You may not append one string literal to another.
Instead you need to define the variable a as a character array large enough to contain the appended string literal pointed to by the pointer b.
And the both functions should be declared like
char *strcpyy(char *dest, const char *orig);
char *strcatt(char *dest, const char *orig);
Also as you are using standard C string functions like strlen
strcpyy(dest + strlen(dest), orig);
then it will be logically consistent to use standard C function strcpy instead of your own function strcpyy.
Otherwise without using standard string functions your function strcatt can look the following way
char * strcatt( char *s1, const char *s2 )
{
char *p = s1;
while ( *p ) ++p;
while ( ( *p++ = *s2++ ) != '\0' );
return s1;
}
Here is a demonstration program.
#include <stdio.h>
char * strcatt( char *s1, const char *s2 )
{
char *p = s1;
while ( *p ) ++p;
while ( ( *p++ = *s2++ ) != '\0' );
return s1;
}
int main( void )
{
char a[7] = "one";
const char *b = "two";
puts( strcatt( a, b ) );
}
The program output is
onetwo
You cannot modify "string literals". Those are not mutable.
The usual idiom for this sort of operation is to build up a string in a temporary working buffer that should be pre-dimensioned large enough to hold all that is required.
The following also shows more obvious code in both your functions.
#include <stdio.h>
char *strcpyy( char *dst, const char *org ) {
for( char *p = dst; (*p++ = *org++) != '\0'; /**/ )
; // loop
return dst;
}
char *strcatt( char *dst, const char *org ) {
char *p = dst;
while( *p != '\0' )
p++; //loop
while( (*p = *org++) != '\0' )
p++; // loop
return dst;
}
int main(){
const char *a = "one ";
const char *b = "two ";
const char *c = "three";
char wrk[ 64 ]; // sufficient mutable space defined
printf( "%s\n", strcatt( strcatt( strcpyy( wrk, a ), b ), c ) );
return 0;
}
one two three

passing string with pointer through function c

i,m trying to write this code, it should counting the number of substring, which are not including in the string, for examples(below), in the main i was trying with pointer to work with String without using arrays but it didnt work at all!!
// count_target_string("abc of", "of") -> 1
// count_target_string("abcof", "of") -> 0
// count_target_string("abc of abc of", "of") -> 2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int countTargetString(char* text , char* string){
char d[]=" ";
char * portion = strtok(text,d);
int result=0;
while (portion!=NULL){
if (strcmp(portion,string)==0){
result++;
}
portion = strtok(NULL,d);
}
return result;
}
int main(){
printf("%d\n",countTargetString("abc of abc of","of"));
char *test ="abc of abc of";
char *d = "of";
printf("%d\n",countTargetString(test,d));
return 0;
}
strtok modifies the string.
char *test ="abc of abc of"; defines the pointer to the string literal. Modification of the string literal invokes Undefined Behaviour (UB). It is why your code does "not work at all" Same if you pass string literal reference directly to the function (ie use a string literal as a parameter) countTargetString("abc of abc of","of"));.
Your pointer must reference a modifiable string:
int main()
{
char mystring[] = "abc of abc of";
char *test = mystring;
char *d = "of";
printf("%d\n",countTargetString(test,d));
}
In the both calls of the function countTargetString
printf("%d\n",countTargetString("abc of abc of","of"));
char *test ="abc of abc of";
char *d = "of";
printf("%d\n",countTargetString(test,d));
you are passing pointers to string literals.
Though in C opposite to C++ string literals have types of non-constant character arrays nevertheless you may not change a string literal. Any attempt to change a string literal results in undefined behavior.
From the C Standard (6.4.5 String literals)
7 It is unspecified whether these arrays are distinct provided their
elements have the appropriate values. If the program attempts to
modify such an array, the behavior is undefined.
And the function strtok changes the source string inserting terminating zero characters '\0' to extract substrings.
It is always better even in C to declare pointers to string literals with the qualifier const.
Instead of the function strtok you can use function strstr.
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
size_t countTargetString( const char *s1, const char *s2 )
{
size_t count = 0;
size_t n = strlen( s2 );
for ( const char *p = s1; ( p = strstr( p, s2 ) ) != NULL; p += n )
{
if ( ( p == s1 || isblank( ( unsigned char )p[-1] ) ) &&
( p[n] == '\0' || isblank( ( unsigned char )p[n] ) ) )
{
++count;
}
}
return count;
}
int main( void )
{
printf("%zu\n",countTargetString("abc of abc of","of"));
const char *test ="abc of abc of";
const char *d = "of";
printf("%zu\n",countTargetString(test,d));
}
The program output is
2
2
As you can see the function parameters are also declared with the qualifier const because the function does not change passed strings.
Pay attention to that in any case to count occurrences of substrings in a string it is a bad idea to change the original string.
While strtok will not work with a string literal, strspn and strcspn can be used.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int countTargetString(char* text , char* string){
char d[]=" ";
int result = 0;
size_t span = 0;
while ( *text) {
text += strspn ( text, d);
span = strcspn ( text, d);
if ( strncmp ( text, string, span)) {
++result;
}
text += span;
}
return result;
}
int main( void) {
printf("%d\n",countTargetString("abc of abc of","of"));
char *test ="abc of abc of";
char *d = "of";
printf("%d\n",countTargetString(test,d));
return 0;
}
int count_substr(const char* target, const char* searched) {
int found = 0;
unsigned long s_len = strlen(searched);
for (int i = 0; target[i]; i++) {
// use memcmp to NOT compare the null terminator of searched
if (memcmp(target + i, searched, s_len) == 0) {
found++;
i += s_len - 1;
}
}
return found;
}
This is a very basic implementation of substring counting. For the fastest solution possible, copy the boyer moore pattern matching algorithm from wikipedia or wherever you want and modify it to cound instead of terminationg on a match.

Is there a function in c that returns the index of a string in another string?

I have 2 char arrays
char page=[4][5] = {{'a','b',' ','d','e'}, {'A',' ','C','D','E'},{'a','b','c','d','e'}, {'A','B','C','D','E'}};
char word[5]="CDE";
I am trying to find the indices of the word "CDE" in page, namely 7 and 17.
Is there a function in C for this? Or a short way.
Something like,
int indexlist[]=findindex(word, page);
You could try the following:
#include <stdio.h>
#include <string.h>
int main(void) {
char page[4][5] = {{'a','b',' ','d','e'}, {'A',' ','C','D','E'},{'a','b','c','d','e'}, {'A','B','C','D','E'}};
char word[5]="CDE";
// put all the characters in a single long string:
char buf[21];
memcpy(buf, &(page[0][0]), 20);
// and null terminate:
buf[20]='\0';
char *p;
p = buf;
while((p = strstr(p, word))!=NULL) {
printf("found a match at offset of %d\n", (int)(p - buf));
p+=strlen(word);
}
}
Output:
found a match at offset of 7
found a match at offset of 17
The closest thing in the standard library is strstr:
char str1[] = "A CDE";
char str2[] = "CDE";
char *p = strstr( str1, str2 );
p now points to the C in str1 (&str1[2]).

Inserting a string into another string no library functions

I am attempting to complete a homework assignment, part of which is to design a function that inserts a string into another string. All functions, with the exception of strlen(), are off limits to me. Specifically the problem is this: I am having trouble implementing the part of the function that "makes room" in the target string for the inserted string. Inserting the string always results in a trampling of array elements. Can anyone point out what I am doing wrong here? Thanks for helping me learn!
Edit: Integer n is the location in the string that I am supposed to insert the other string.
void insertstring(char *str, char *ins, int n)
{
int i;
int scoot=strlen(ins);
char *p=str+n;
for (i=strlen(str); i > n; --i) { //This is where I'm doing it wrong I think
str[i+scoot]=str[i]; //
}
do {
*p = *ins;
++p;
++ins;
}
while (*ins != '\0');
}
An elegant solution uses reversing to achieve the desired result. Assume your target string, str, is composed of two blocks, AB, where A is the block before the insertion point, and B is the block after insertion point. Furthermore, assume that the string to insert, ins, is denoted by a third block C.
It can be seen that if you concatenate C to AB and then reverse B, reverse C, and reverse both B and C, you get ACB, which is the desired result. More explicitly, this is what you have after appending C to AB:
ABC
And this is what you want:
ACB
ACB can be obtained by:
Reverse B, to get B_r (B reversed);
Reverse C, to get C_r - at this point we have AB_rC_r;
Reverse both B and C, that is, compute A(B_rC_r)_r, which yields ACB.
Here's the code that implements this algorithm:
void reverse(char *, char *, char *);
/* Insert string C between blocks AB in str */
void insertstring(char *str, char *ins, int n) {
/* 1 - Append C to the end of str */
int i = strlen(str);
char *p = str+i, *q = ins;
while ((*p++ = *q++));
p--;
/* 2 - Reverse C and B */
reverse(str, str+i, p-1); /* C */
reverse(str, str+n, str+i-1); /* B */
/* 3 - Reverse B_rC_r */
reverse(str, str+n, p-1);
}
void reverse(char *str, char *begin, char *end) {
char tmp;
while (begin < end) {
tmp = *begin;
*begin = *end;
*end = tmp;
begin++;
end--;
}
}
And some sample code to test it:
#include <stdio.h>
#include <string.h>
int main() {
void insertstring(char *, char *, int);
char test[128] = "A string to test.";
printf("Before: %s\n", test);
insertstring(test, "hello!", 4);
printf("After: %s\n", test);
return 0;
}
This will insert "hello!" beginning in test[4]. Here's the output:
$ ./test
Before: A string to test.
After: A sthello!ring to test.
Consider taking this approach: the code is short and elegant. This technique is described in Programming Pearls, 2nd edition, as a good way to perform vector rotation. According to the author, Brian Kernighan and P.J. Plauger used precisely this method in their Software Tools in Pascal to move lines within a text editor.
First you have change
for (i=strlen(str); i > n; --i)
to
for (i=strlen(str); i >= n; --i)
because you have to move str[n] too.
The other problem is when you insert ins:
do {
*p = *ins;
++p;
++ins;
}
while (*ins != '\0');
Here you copy the terminating '\0' from ins to str so the rest is lost. Change it to
while (*ins != '\0') {
*p = *ins;
++p;
++ins;
}
After mentioning about n, update for loop as
for (i=n+scoot; i >= n; i--)
You want to move strlen(ins) number of character ahead from location n.
Tried it with single loop,
go to index , copy src content into temp_array and simultaneously copying medi into src
once medi is copied completely , start putting the content of temp_array till it become empty
void insert_in_middle (char *src, char *medi, int index)
{
int i=0, j = index, k=0;
char temp_array[50];
while(src[j] != '\0' || temp_array[k] != '\0')
{
temp_array[i] = src[j];
if(medi[i] != '\0')
{
src[j] = medi[i];
}
else if(temp_array[k] != '\0')
{
src[j] = temp_array[k];
k++;
}
i++; j++;
}
printf("src[%s]\n", src);
printf("medi[%s]\n",medi);
printf("temp_array[%s]\n",temp_array);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *str_ins();
int main()
{
char *test = "Hello, world!";
printf("%s\n",test);
str_ins(&test,strstr(test,"world"),"my ");
printf("%s\n",test);
}
char *str_ins(a, b, c) // insert string c into a at point b
char **a, *b, *c;
{
char *stemp;
int pos = strlen(*a) - strlen(b);
stemp = (char *) malloc(strlen(*a)+strlen(c)+1);
strncpy(stemp,*a,pos);
strcpy(stemp+pos,c);
strcat(stemp,b);
free(a);
*a = stemp;
return *a;
}

Resources